Просто добавление информации, которой нет в других ответах.
Если доступно procfs /proc/self/cmdline
Если вы работаете в среде, которая предоставляет procfs и, следовательно, имеет файловую систему /proc
(что означает, что это не переносимое решение), вы можете иметь Java для чтения /proc/self/cmdline
, чтобы перезапустить себя, например так:
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();
}
}
В системах с /proc/self/cmdline
это, вероятно, самый элегантный способ «перезапустить» текущий процесс Java из Java.Никакой JNI не задействован, и не нужно угадывать пути и прочее.Это также позаботится обо всех параметрах JVM, переданных в двоичный файл java
.Командная строка будет точно такой же, как и у текущего процесса JVM.
Многие UNIX-системы, включая GNU / Linux (включая Android), в настоящее время имеют procfs Однако нанекоторые, такие как FreeBSD, устарели и постепенно исчезают. Mac OS X является исключением в том смысле, что не имеет procfs . Windows также не имеет procfs .У Cygwin есть procfs , но он невидим для Java, потому что он виден только приложениям, использующим библиотеки Cygwin вместо системных вызовов Windows, а Java не знает о Cygwin.
Не забудьте использовать ProcessBuilder.inheritIO()
По умолчанию stdin
/ stdout
/ stderr
(в Java называется System.in
/ System.out
/ System.err
) запущенного процесса установлены на трубы, которые позволяют текущему процессу взаимодействовать с недавно запущенным процессом.Если вы хотите перезапустить текущий процесс, это , скорее всего, не то, что вы хотите .Вместо этого вы бы хотели, чтобы stdin
/ stdout
/ stderr
были такими же, как у текущей виртуальной машины.Это называется наследуется .Вы можете сделать это, вызвав inheritIO()
вашего ProcessBuilder
экземпляра.
Подводный камень в Windows
Частым случаем использования функции restart()
является перезапуск приложения после обновления.В прошлый раз, когда я попробовал это на Windows, это было проблематично.Когда файл новой версии .jar
был перезаписан новой версией, приложение начало плохо себя вести и выдавало исключения для файла .jar
.Я просто говорю, на случай, если это ваш вариант использования.Тогда я решил эту проблему, поместив приложение в пакетный файл и использовав магическое возвращаемое значение из System.exit()
, которое я запросил в пакетном файле, и вместо этого пакетный файл перезапустил приложение.