Редактировать: Мне кажется, что мой тест для определения того, был ли исходный выход JVM, был некорректным для начала (см. Комментарии к принятому ответу). Извините за шум.
У меня естьнеобходимо, чтобы запущенная JVM запустила другую JVM и затем вышла.В настоящее время я пытаюсь сделать это через Runtime.getRuntime().exec()
.Запускается другая JVM, но моя исходная JVM не завершится, пока не остановится «дочерний» процесс JVM.Похоже, что использование Runtime.getRuntime().exec()
создает отношения родитель-потомок между процессами.Есть ли какой-нибудь способ отсоединить порожденный процесс, чтобы родитель мог умереть, или какой-то другой механизм, чтобы порождать процесс без какого-либо отношения к процессу создания?
Обратите внимание, что это выглядит в точности как этот вопрос: Использование Java для порождения процесса и продолжения его работы после выхода из родительского процесса , но принятый там ответ на самом деле не работает, по крайней мере, в моей системе (Windows 7, Java 5 и 6).Похоже, что это может зависеть от платформы.Я ищу платформу независимый способ надежно вызвать другой процесс и позволить моему исходному процессу умереть.
Например, предположим, у меня есть файл jar на C:\myjar.jar
, и я хочузапустить класс com.example.RunMe
, который живет в этой банке.Допустим, класс вызывает всплывающую панель JOptionPane и завершает работу, когда пользователь нажимает кнопку ОК.
Теперь программа, выполняющаяся в JVM # 1:
public static void main(String[] args) {
String javaHome = System.getProperty("java.home");
String os = System.getProperty("os.name");
String javawBin = javaHome + File.separator + "bin" + File.separator + "javaw";
if (os.toLowerCase().contains("win")) {
javawBin += ".exe";
}
List<String> cmd = new ArrayList<String>();
cmd.add("\"" + javawBin + "\"");
cmd.add("-cp");
cmd.add("\"C:\\myjar.jar\"");
cmd.add("com.example.RunMe");
System.out.println("Running: " + cmd);
try {
System.out.println("Launching...");
Process p = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
new Thread(new StreamGobbler(p.getInputStream())).start();
new Thread(new StreamGobbler(p.getErrorStream())).start();
System.out.println("Launched JVM.");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
private static class StreamGobbler implements Runnable {
InputStream stream;
StreamGobbler(InputStream stream) {
this.stream = stream;
}
public void run() {
byte[] buf = new byte[64];
try {
while (stream.read(buf) != -1)
;
} catch (IOException e) {
}
}
}
Наблюдаемое поведениеявляется то, что оба «Запуск ...» и «Запущенная JVM».печатаются, но JVM # 1 завершается только после того, как вы нажмете OK в JOptionPane, запущенной JVM # 2.Кроме того, поведение одинаково, независимо от того, запускаете ли вы потоки гоблеров потока или нет.
Кроме того, чтобы сохранить кому-то дыхание, да, я знаю, что мог бы создать новый URLClassLoader с этим файлом JAR и запустить еготаким образом, но это не то, что я пытаюсь сделать здесь.