Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime.exec().waitFor() not actually waiting for

I've got some code that uses Runtime.exec() to run an external .jar (built as an IzPack installer).

If I run this external.jar from the command line like so:

java -jar external.jar

Then the command prompt does not return control until the application is finished. However, if I run external.jar from within some java class, using:

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

Then p returns almost instantly with a success code of 0, despite external.jar having not yet completed execution (i've also tried this via the ProcessBuilder route of external file execution).

Why does it wait to return from the command line, but not when executed from within another java program?

I've also set up 3 jars, A, B and C where A calls B which calls C (using Runtime.exec()), where C Thread.sleeps for 10 seconds, as a simple test, and as expected, A doesn't return until 10 seconds after it runs.

I figure this is probably some kind of a threading issue with external.jar where execution is being handed over from one thing to another, but given that it works directly from the command line i kind of expected to see the same behaviour (perhaps naively) when called from within another java program.

I've tested this on Windows and Ubuntu with Java 6.

Thanks!

like image 350
Rhys Avatar asked Jul 05 '12 18:07

Rhys


People also ask

What is process WaitFor ()?

WaitFor() Causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. WaitFor(Int64, TimeUnit) Causes the current thread to wait, if necessary, until the subprocess represented by this Process object has terminated, or the specified waiting time elapses.

How do you make a Java process wait?

The waitFor() method of Process class is used to wait the currently executing thread until the process executed by the Process object has been completed. The method returns immediately when the subprocess has been terminated and if the subprocess is not terminated, the thread will be blocked.

What is runtime getRuntime () exec?

In Java, the Runtime class is used to interact with Every Java application that has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime() method.

What is the Java process?

Process provides control of native processes started by ProcessBuilder. start and Runtime. exec. The class provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.


1 Answers

another possible way to achieve this might be to capture the output of the process and wait for it to finish.

For example:

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
}

Normally the output stream is tr.getInputStream() but depending on the program you are executing the process output stream migh be:

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

By doing this while loop you force your program to wait the process to finish.

like image 92
antonio_Developer Avatar answered Oct 03 '22 09:10

antonio_Developer