it-swarm.com.ru

Runtime.exec (). WaitFor () фактически не ожидает

У меня есть некоторый код, который использует Runtime.exec () для запуска внешнего .jar (построен как установщик IzPack).

Если я запускаю этот external.jar из командной строки примерно так:

Java -jar external.jar

Тогда команда Prompt не возвращает управление, пока приложение не будет завершено. Однако, если я запускаю external.jar из какого-то класса Java, используя:

Process p = Runtime.getRuntime().exec("Java -jar external.jar");
int exitCode = p.waitFor();
System.out.println("Process p returned: " + exitCode);

Затем p почти мгновенно возвращается с кодом успеха 0, несмотря на то, что external.jar еще не завершил выполнение (я также пробовал это через маршрут ProcessBuilder выполнения внешнего файла).

Почему он ожидает возврата из командной строки, а не при выполнении из другой программы Java?

Я также установил 3 банки, A, B и C, где A вызывает B, который вызывает C (используя Runtime.exec()), где C Thread.sleeps в течение 10 секунд, в качестве простого теста, и, как и ожидалось, A не возвращается до 10 секунд после того, как это бежит.

Я полагаю, что это, вероятно, какая-то проблема с многопоточностью в external.jar, когда выполнение передается от одного к другому, но, учитывая, что оно работает напрямую из командной строки, я ожидал увидеть то же поведение (возможно, наивно) при вызове из другой программы Java.

Я проверил это в Windows и Ubuntu с помощью Java 6.

Спасибо!

12
Rhys

другим возможным способом достижения этого может быть захват результатов процесса и ожидание его завершения.

Например:

Process tr = Runtime.getRuntime().exec( new String[]{"wkhtmltopdf",mainPage,mainPagePDF});
BufferedReader stdOut=new BufferedReader(new InputStreamReader(tr.getInputStream()));
String s;
while((s=stdOut.readLine())!=null){
       //nothing or print
}

Обычно выходным потоком является tr.getInputStream (), но в зависимости от программы, которую вы выполняете, выходной поток процесса может быть:

  • tr.getInputStream ()
  • tr.getErrorStream ()
  • tr.getOutputStream ()

Выполняя этот цикл while, вы заставляете свою программу ждать завершения процесса.

6
antonio_Developer

Вы можете использовать Process Builder ....

ProcessBuilder pb = new ProcessBuilder("Java", "-jar", "/fielname.jar");
Process p = pb.start();
p.waitFor();
1
Vishal Bhosale

Вы порождаете новую нить, чтобы справиться с порождением процесса? В этом случае исходная программа будет продолжать работать независимо от порожденного процесса, и поэтому waitFor () будет работать только с новым процессом, а не с родительским.

0
Matt Westlake