Process.exitValue()和Process.destroy()function

我一直在使用ProcessProcessBuilder进行实验,并带着这个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()); } } 
  1. 如果我运行此代码并在10秒超时前closures记事本。 destroy()调用在尝试停止已经终止的进程时不显示任何问题。 为什么?
  2. 如果运行这个代码,并且根本不closures记事本(带有注释的第二个睡眠)

看来,销毁是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) 
  1. 如果我运行这个代码,并且根本不closures记事本(没有注释的第二个睡眠),那么第二个exitValue永远不会抛出exception,即使睡眠值只是1ms。 是因为sleep()开销本身? 第二个exitValue将返回1。

PS。 我从Windows 7和Eclipse运行它。

  1. 为什么显示一个问题? 你试图摧毁一个已经被破坏的进程。 Process.destroy()的规范并没有说如果没有什么可以销毁的话会发生什么情况,所以假设没有什么东西可以销毁是合乎逻辑的(我想),那么没有什么可抱怨的。 与Thread.join()比较,如果线程已经结束,它不会死。

  2. 杀死一个进程的唯一方法是发送一个信号。 在一些操作系统上,还有其他更“暴力”的方式(在某些平台上,例如,可以简单地将进程从正在运行的进程列表中删除,结果是未定义的,通常结尾是丑陋的),但是至少我知道的平台,其实全是关于发送信号。

  3. 可能的确,这是因为调用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中,对应于SIGTERMhttps://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()); }