Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 4
A more thorough look at the methods available in the Process class reveals a waitFor() method that does precisely that. In fact, waitFor() also returns the exit value, which means that you would not use exitValue() and waitFor() in conjunction with each other, but rather would choose one or the other. The only possible time you would use exitValue() instead of waitFor() would be when you don't want your program to block waiting on an external process that may never complete. Instead of using
the waitFor() method, I would prefer passing a boolean parameter called waitFor into the exitValue() method to determine whether or not the current thread should wait. A boolean would be more beneficial because exitValue() is a more appropriate name for this method, and it isn't necessary for two methods to perform the same function under different
conditions. Such simple condition discrimination is the domain of an input parameter.
Therefore, to avoid this trap, either catch the IllegalThreadStateException or wait for the process to complete.
Now, let's fix the problem in Listing 4.1 and wait for the process to complete. In Listing 4.2, the program again attempts
to execute javac.exe and then waits for the external process to complete:
Listing 4.2 BadExecJavac2.java
import java.util.*;
import java.io.*;
public class BadExecJavac2
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
Unfortunately, a run of BadExecJavac2 produces no output. The program hangs and never completes. Why does the javac process never complete?
The JDK's Javadoc documentation provides the answer to this question:
Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.
Is this just a case of programmers not reading the documentation, as implied in the oft-quoted advice: read the fine manual (RTFM)? The answer is partially yes. In this case, reading the Javadoc would get you halfway there; it explains that you need to handle the streams to your external process, but it does not tell you how.
Another variable is at play here, as is evident by the large number of programmer questions and misconceptions concerning
this API in the newsgroups: though Runtime.exec() and the Process APIs seem extremely simple, that simplicity is deceiving because the simple, or obvious, use of the API is
prone to error. The lesson here for the API designer is to reserve simple APIs for simple operations. Operations prone to
complexities and platform-specific dependencies should reflect the domain accurately. It is possible for an abstraction to
be carried too far. The JConfig library provides an example of a more complete API to handle file and process operations (see Resources below for more information).
JConfig library or download it for evaluation