我一直在使用Process
和ProcessBuilder
进行实验,并带着这个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()); } }
destroy()
调用在尝试停止已经终止的进程时不显示任何问题。 为什么? 看来,销毁是asynchronous调用( 只是发送一个信号? )导致在第二个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)
exitValue
永远不会抛出exception,即使睡眠值只是1ms。 是因为sleep()
开销本身? 第二个exitValue
将返回1。 PS。 我从Windows 7和Eclipse运行它。
为什么会显示一个问题? 你试图摧毁一个已经被破坏的进程。 Process.destroy()
的规范并没有说如果没有什么可以销毁的话会发生什么情况,所以假设没有什么东西可以销毁是合乎逻辑的(我想),那么没有什么可抱怨的。 与Thread.join()
比较,如果线程已经结束,它不会死。
杀死一个进程的唯一方法是发送一个信号。 在一些操作系统上,还有其他更“暴力”的方式(在某些平台上,例如,可以简单地将进程从正在运行的进程列表中删除,结果是未定义的,通常结尾是丑陋的),但是至少我知道的平台,其实全是关于发送信号。
可能的确,这是因为调用Thread.sleep()
需要时间。 尝试增加超时值。
我期望destroy()方法正在调用本地窗口函数TerminateProcess。 看着MSDN ,我发现这个:
TerminateProcess是异步的; 它立即终止并返回。 如果您需要确定进程已经终止,请调用WaitForSingleObject函数,并使用该进程的句柄。
所以我认为这解释了销毁确实是异步的。
来自同一来源的另一个摘录:
TerminateProcess函数用于无条件地导致进程退出。
我猜测“非空间”可以解释为什么在终止进程上调用destroy()不会失败。
希望这个帮助。 (非常有趣的问题!)
ProcessImpl.java
上的destroy
方法调用本地函数terminateProcess
:
public void destroy() { terminateProcess(handle); } private static native void terminateProcess(long handle);
terminateProcess
是平台相关的,对于Windows,您可以在这里找到源代码。 这只是调用Windows TerminateProcess函数(链接到这个函数是在以前的答案,或者你可以谷歌它)与uExitCode=1
– 这就是为什么退出代码被销毁的进程是1
。
在linux看起来像是使用类似这样的东西。 作为证明,下一个代码返回143
在Ubuntu中,对应于SIGTERM
( https://stackoverflow.com/a/4192488/3181901 ):
public static void main(final String[] args) throws IOException, InterruptedException { final Process process = Runtime.getRuntime().exec(args[0]); process.destroy(); Thread.sleep(1000); System.out.println(process.exitValue()); }