Править: Это кажется моим тестом, чтобы определить, вышла ли исходная JVM, был испорчен для начала (см. комментарии к принятому ответу). Извините за шум.
У меня есть потребность иметь рабочую JVM, запускают другую JVM и затем выходят. Я в настоящее время пытаюсь сделать это через Runtime.getRuntime().exec()
. Другая JVM запускается, но моя исходная JVM не выйдет, пока "дочерний" процесс JVM не останавливается. Это появляется то использование Runtime.getRuntime().exec()
создает отношения отцов и детей между процессами. Там некоторый путь состоит в том, чтобы отделить порожденный процесс так, чтобы родитель мог умереть, или некоторый другой механизм для порождения процесса без каких-либо отношений к процессу создания?
Обратите внимание, что это точно походит на этот вопрос: Используя Java, чтобы породить процесс и сохранить его бегущий за родительскими выходами, но принятым ответом там на самом деле не работает, по крайней мере, не в моей системе (Windows 7, Java 5 и 6). Кажется, что, возможно, это - зависимое от платформы поведение. Я ищу независимый от платформы способ надежно вызвать другой процесс и позволить моему исходному процессу умереть.
Например, предположите, что у меня есть файл банки в 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 cmd = new ArrayList();
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 только выходит после удара хорошо в JOptionPane, запущенном JVM № 2. Также - поведение является тем же, начинаете ли Вы против течения потоки индюка или нет.
Кроме того, для сохранения кого-то дыхание да, я знаю, что мог создать новый URLClassLoader с тем файлом банки и выполнить его тот путь, но это не то, что я пытаюсь сделать здесь.
Я только что попробовал следующий код, и я вижу порождение процессов и выход главного из них на Vista и Java 6. Я думаю, что с вашим кодом может происходить что-то другое.
public class Test {
public static void main(String[] args) throws Exception {
if(args.length == 0)
Runtime.getRuntime().exec("javaw Test loop");
else
while(true){}
}
}
Насколько мне известно, завершение процесса довольно часто приводит к уничтожению всех дочерних процессов. Я сомневаюсь, что есть независимый от платформы способ сделать это.
Windows не устанавливает между процессами отношения "родитель-ребенок", как это делают системы Unix. Вполне вероятно, что ваш родительский процесс не завершается, потому что в нем все еще выполняется поток. Этот поток может ждать завершения дочернего процесса, что может объяснить, почему родительский процесс завершается, когда завершается дочерний.
Ваши потоки, выполняющие StreamGobblers
, находятся внутри процесса №1 и не являются потоками демона, поэтому процесс №1 не завершается до тех пор, пока эти потоки не будут завершены, когда потоки они поглощение уйти, как только процесс № 2 закончится.
Выньте две линии, которые образуют эти нити.