Как перезапустить приложение Java?
Как перезапустить приложение Java AWT? У меня есть кнопка, к которой я прикрепил обработчик событий. Какой код я должен использовать для перезапуска приложения?
Я хочу сделать то же самое, что делает Application.Restart() в приложении C#.
Конечно, это возможно, чтобы перезапустить приложение Java.
Следующий метод показывает способ перезагрузка Java-приложения:
public void restartApplication() < final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; final File currentJar = new File(MyClassInTheJar.class.getProtectionDomain().getCodeSource().getLocation().toURI()); /* is it a jar file? */ if(!currentJar.getName().endsWith(".jar")) return; /* Build command: java -jar application.jar */ final ArrayListcommand = new ArrayList(); command.add(javaBin); command.add("-jar"); command.add(currentJar.getPath()); final ProcessBuilder builder = new ProcessBuilder(command); builder.start(); System.exit(0); >
В основном она выполняет следующие действия:
- Найти исполняемый файл Java (я использовал здесь двоичному файлу Java, но это зависит от ваших требований)
- Найти приложение (банку в моем случае, с помощью MyClassInTheJar класса, чтобы найти себе место банку)
- Построить команду, чтобы перезапустить банку (используя двоичному файлу Java в данном случае)
- Выполнить его! (и, следовательно, завершение текущего приложения и запустить его снова)
import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; public class Main < public static void main(String[] args) throws IOException, InterruptedException < StringBuilder cmd = new StringBuilder(); cmd.append(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java "); for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) < cmd.append(jvmArg + " "); >cmd.append("-cp ").append(ManagementFactory.getRuntimeMXBean().getClassPath()).append(" "); cmd.append(Main.class.getName()).append(" "); for (String arg : args) < cmd.append(arg).append(" "); >Runtime.getRuntime().exec(cmd.toString()); System.exit(0); > >
Посвящается всем тем, кто говорят, что это невозможно.
Эта программа собирает всю имеющуюся информацию, чтобы воссоздать первоначальный командной строке. После этого, он запускает его, и так как это же прикажете, Ваше приложение запускается во второй раз. Затем мы выходим из исходной программы, программы детей по-прежнему работает (даже под Linux) и делает то же самое.
Предупреждение: Если вы запустите это, имейте в виду, что это никогда не закончится создание новых процессов, похожий на таблиц.
В принципе, нельзя. По крайней мере, не надежным способом.
Чтобы перезапустить программу Java, вам нужно перезапустить JVM. Чтобы перезапустить JVM, вам нужно
- Найти java launcher, который был использован. Вы можете попробовать использовать System.getProperty(«java.home») , но нет никакой гарантии, что это действительно укажет на программу запуска, которая использовалась для запуска вашего приложения. (Возвращаемое значение может не указывать на JRE, используемую для запуска приложения или оно может быть переопределено -Djava.home ).
- Предположительно, вы хотите сохранить исходные настройки памяти и т.д. ( -Xmx , -Xms , …), поэтому вам нужно выяснить, какие настройки использовались для запуска первой JVM. Вы можете попробовать использовать ManagementFactory.getRuntimeMXBean().getInputArguments() , но нет никакой гарантии, что это отразит использованные настройки. Это даже прописано в документации этого метода:
Как правило, не все параметры командной строки команды ‘java’ передаются виртуальной машине Java. Таким образом, возвращаемые входные аргументы могут включать не все параметры командной строки.
- Если ваша программа считывает входные данные из Standard.in , исходный stdin будет потерян при перезапуске.
- Многие из этих трюков и хаков потерпят неудачу в присутствии SecurityManager .
С другой стороны: Вам не должно это понадобиться.
Я рекомендую вам спроектировать ваше приложение так, чтобы было легко все очистить, а после этого создать новый экземпляр вашего класса «main».
Многие приложения спроектированы так, что не делают ничего, кроме создания экземпляра в методе main:
Используя этот шаблон, должно быть достаточно легко сделать что-то вроде:
public class MainClass < . public static void main(String[] args) < boolean restart; do < restart = new MainClass().launch(); >while (restart); > . >
и пусть launch() возвращает true, если и только если приложение было закрыто таким образом, что его нужно перезапустить.
Строго говоря, программа Java не может перезапустить себя сама, поскольку для этого она должна убить JVM, в которой она запущена, а затем запустить ее снова, но если JVM больше не запущена (убита), то никаких действий предпринять нельзя.
Можно проделать некоторые трюки с пользовательскими загрузчиками классов, чтобы загрузить, упаковать и снова запустить компоненты AWT, но это, вероятно, вызовет много головной боли в отношении цикла событий GUI.
В зависимости от того, как запускается приложение, вы можете запустить JVM в сценарии-обертке, содержащем цикл do/while, который продолжается до тех пор, пока JVM не выйдет с определенным кодом, тогда AWT-приложение должно будет вызвать System.exit(RESTART_CODE) . Например, в псевдокоде сценария:
DO # Launch the awt program EXIT_CODE = # Get the exit code of the last process WHILE (EXIT_CODE == RESTART_CODE)
Приложение AWT должно выйти из JVM с каким-то другим кодом, отличным от RESTART_CODE при «нормальном» завершении, которое не требует перезапуска.
Затмения обычно перезагружается после установки плагина. Они делают это с помощью eclipse.exe фантик (запуска приложения) для Windows. Это приложение исполняет основной бегун затмение jar и если приложение Eclipse на Java завершается перезапуска код, eclipse.exe перезапускает верстак. Вы можете построить подобный немного машинный код, скрипт или другой обертке код Java, чтобы добиться перезагрузки.
Хотя этот вопрос старый и ответ, Я’вэ наткнулся на проблемы с некоторыми решениями и решила добавить свое предложение в эту смесь.
Проблема с некоторыми из решений заключается в том, что они строят единую командную строку. Это создает проблемы, когда некоторые параметры содержат пробелы, особенно Ява.домой.
Например, в Windows, строки
final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
Может вернуть что-то вроде этого: C:\Program файлы\папку Java\jre7\bin и\Ява
Эту строку необходимо заключить в кавычки или сбежавших из-за пространство в программы и файлы. Не огромная проблема, но немного раздражает и подвержен ошибкам, особенно в кроссплатформенных приложений.
Поэтому мое решение создает команду в качестве массива команд:
public static void restart(String[] args) < ArrayListcommands = new ArrayList(4 + jvmArgs.size() + args.length); List jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); // Java commands.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"); // Jvm arguments for (String jvmArg : jvmArgs) < commands.add(jvmArg); >// Classpath commands.add("-cp"); commands.add(ManagementFactory.getRuntimeMXBean().getClassPath()); // Class to be executed commands.add(BGAgent.class.getName()); // Command line arguments for (String arg : args) < commands.add(arg); >File workingDir = null; // Null working dir means that the child uses the same working directory String[] env = null; // Null env means that the child uses the same environment String[] commandArray = new String[commands.size()]; commandArray = commands.toArray(commandArray); try < Runtime.getRuntime().exec(commandArray, env, workingDir); System.exit(0); >catch (IOException e) < e.printStackTrace(); >>
Если вам действительно нужно перезапустить приложение, вы можете написать отдельное приложение для его запуска.
На этой странице приведено множество примеров для различных сценариев:
/мин для запуска скрипта в свернутом окне
^&ампер; выход, чтобы закрыть окно cmd после финиша
может быть пример скрипта УМК
@echo off rem add some sleep (e.g. 10 seconds) to allow the preceding application instance to release any open resources (like ports) and exit gracefully, otherwise the new instance could fail to start sleep 10 set path=C:\someFolder\application_lib\libs;%path% java -jar application.jar
сон 10 спать на 10 секунд
Я исследовал эту тему сам, когда наткнулся на этот вопрос.
Несмотря на то, что ответ уже принят, но я хотел бы предложить альтернативный подход для полноты. В частности, Апач АНТ служил очень гибкое решение.
В основном, все сводится в файл Ant-скрипт с одного задания выполнение Java (см. здесь и здесь) вызывается из Java-кода (см. здесь). Этот Java-код, который может быть метод запустить, может быть частью приложения, который должен быть перезапущен. Приложение должно иметь зависимость от библиотеки Apache Муравей (банку).
Всякий раз, когда приложение должно быть перезапущен, он должен вызвать метод запуск и выхода ВМ. Ant-задачу на Java должны иметь варианты вилка и Спаун значение true.
Код для запуска метод может выглядеть примерно так:
public final void launch(final String antScriptFile) < /* configure Ant and execute the task */ final File buildFile = new File(antScriptFile); final Project p = new Project(); p.setUserProperty("ant.file", buildFile.getAbsolutePath()); final DefaultLogger consoleLogger = new DefaultLogger(); consoleLogger.setErrorPrintStream(System.err); consoleLogger.setOutputPrintStream(System.out); consoleLogger.setMessageOutputLevel(Project.MSG_INFO); p.addBuildListener(consoleLogger); try < p.fireBuildStarted(); p.init(); final ProjectHelper helper = ProjectHelper.getProjectHelper(); p.addReference("ant.projectHelper", helper); helper.parse(p, buildFile); p.executeTarget(p.getDefaultTarget()); p.fireBuildFinished(null); >catch (final BuildException e) < p.fireBuildFinished(e); >/* exit the current VM */ System.exit(0);
Очень удобная вещь здесь заключается в том, что тот же скрипт используется на начальном запуске, а также при перезагрузке.
Просто добавляя информацию, отсутствующую в других ответов.
Если procfs `/proc и/самостоятельной/командной строки доступна
Если вы работаете в среде, которая обеспечивает procfs и, следовательно, имеет `в/proc файловой системе доступны (что означает, что это не портативное решение), вы можете иметь Java чтение файла/proc/самостоятельной/командной строки для того, чтобы перезагрузить себя, такой:
public static void restart() throws IOException < new ProcessBuilder(getMyOwnCmdLine()).inheritIO().start(); >public static String[] getMyOwnCmdLine() throws IOException < return readFirstLine("/proc/self/cmdline").split("\u0000"); >public static String readFirstLine(final String filename) throws IOException < try (final BufferedReader in = new BufferedReader(new FileReader(filename))) < return in.readLine(); >>
В системах с доступен текстовый командной строки , это, вероятно, самый элегантный способ, чтобы «перезагрузка» в текущем процесса Java от Java. Не JNI участвует, и не гадать путей и прочее необходимое. Это также будет заботиться о всех опций JVM перешла к Ява бинарные. В командной строке будет точно идентичного текущего процесса JVM.
Многие UNIX-систем, включая GNU/Linux (включая Android), в настоящее время у procfs, однако на некоторые, как во FreeBSD, это устаревшие и постепенно сходит на нет. Мас OS X является исключение в том смысле, что он не имеет procfs. Окна нет procfs. В Cygwin есть procfs но это’s невидимым для Java, потому что это’s только видимым для приложений, использующих пакет Cygwin вместо Windows системные вызовы, и Java не под Cygwin.
Дон’т забывайте использовать ProcessBuilder.inheritIO()`
По умолчанию предполагается, что стандартный ввод / стандартный вывод / стандартный вывод (в Java называемую систему .в / Система .из системы/ .ошибка ) начатого процесса имеют значение *трубы*, которые позволяют запущенных процессов для взаимодействия с вновь запущен процесс. Если вы хотите, чтобы перезагрузить текущий процесс, это *скорее всего, не то, что вы хотите*. Вместо этого вы хотите что стандартный ввод / стандартный вывод / стандартный вывод такие же, как у текущей виртуальной машины. Это называется *наследство*. Вы можете сделать это путем вызова inheritIO() в экземпляре ProcessBuilder .
Ошибка в Windows
Частый случай использования перезапуск (функция) состоит в том, чтобы перезапустить приложение после обновления. Последний раз я пробовал это на Windows, это было проблематично. Когда переписал приложение'ы .файл jar с новой версией, приложение, начали безобразничать и предоставление исключений о .файл jar . Я’м просто говорю, в случае, если это ваш случай использования. Тогда я решил проблему путем заключения приложения в пакетном файле и с помощью магии вернуть значение из системы.выход () , что я порылся в пакетный файл и батник вместо того, чтобы перезапустить приложение.
Как перезапустить программу Java изнутри Java?
У меня есть java-программа, которая довольно велика, и мы хотим сделать так, чтобы пользователь мог выйти из приложения и войти в систему как другой пользователь. Для этого мы хотели бы закрыть приложение и перезапустить его, чтобы он представлял пользователю диалог входа в систему. Проблема в том, что приложение довольно велико и плохо написано. Он имеет множество статических переменных, которые содержат некоторую информацию о состоянии. В идеале я хотел бы переписать приложение, чтобы справиться с ситуацией, когда все они могут быть очищены, но на самом деле мы должны обеспечить эту функциональность как можно скорее. То, что я думал, было бы проще всего просто остановить приложение и запустить новый vm. Тем не менее, на удивление сложно остановить и применить приложение и запустить одно и то же приложение, закрыв текущий. Кто-нибудь имеет опыт этого? EDIT: мы продолжаем использовать Runtime.exec для повторного вызова того же приложения, но exec() хочет блокировать, поэтому нам нужно перепрыгнуть через обручи, чтобы он работал на каждой платформе (Windows, Mac, Linux). Я бы предпочел независимый от платформы способ сделать это.
На этот вопрос есть ответ с использованием ProcessBuilder , который рекомендуется в документации для Runtime.exex(cmdarray, envp, dir) . «ProcessBuilder.start () теперь является предпочтительным способом запуска процесса с измененной средой».
Мне действительно нравится, как JBoss справляется с этим. Я не уверен, как это делается в Windows, но в * nix вы запускаете ваше приложение в цикле while, который проверяет код выхода вашего приложения. В JBoss, если вы скажете ему выйти с кодом 10, этот скрипт перезапустит его.