I have been experimenting with Process and ProcessBuilder and come with this SSCCE.
import java.io.IOException;
public class TestProcess {
public static void main(String[] args) {
Process process = null;
ProcessBuilder pb = new ProcessBuilder("notepad.exe");
try {
process = pb.start();
} catch (IOException e) {e.printStackTrace();}
//have some time to close notepad
try {
Thread.sleep(10*1000);
} catch (InterruptedException ignored) {}
try {
System.out.println(process.exitValue());
} catch (IllegalThreadStateException e) {
System.out.println(e);
}
if (process != null)
process.destroy();
/*try {
Thread.sleep(0, 1);
} catch (InterruptedException ignored) {}*/
System.out.println(process.exitValue());
}
}
- If I run this code and close notepad before 10s timeout.
destroy()call does not show any problem on attempt to stop already terminated process. Why? - If run this code and don’t close notepad at all (with commented second sleep)
It seems that destroy is asynchronous call (just sending a signal?) which results in exception in second exitValue()
java.lang.IllegalThreadStateException: process has not exited
Exception in thread "main" java.lang.IllegalThreadStateException: process has not exited
at java.lang.ProcessImpl.exitValue(ProcessImpl.java:246)
at TestProcess.main(TestProcess.java:30)
- If I run this code and don’t close notepad at all (with uncommented second sleep) then second
exitValuenever throws Exception, even though sleep value is just 1ms. Is it because ofsleep()overhead itself?
SecondexitValuewould return 1.
PS. I run it from Windows 7 and Eclipse.
Why would it show a problem? You’re trying to destroy a process that was already destroyed. The specification of
Process.destroy()doesn’t say what happens if there was nothing to destroy, so it is logical (I suppose) to assume that if there’s nothing to destroy, then there’s nothing to complain about. Compare withThread.join(), which doesn’t just die if the thread has already ended.The only way to kill a process is to send it a signal. On some OS’s, there are other, more “violent” ways (on some platforms, for example, it is possible to simply remove the process from the OS’s list of running processes. Results are undefined and it usually ends ugly), but at least with platforms that I know of, it’s really all about sending signals.
Possible, indeed, that it’s because it takes time to invoke
Thread.sleep(). Try increasing the timeout value.