java进程。exitValue()和进程。销毁()功能
我一直在用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());
}
}
- 如果我运行此代码并在10秒超时前关闭记事本
destroy()
调用在尝试停止已终止的进程时未显示任何问题为什么强> - 如果运行此代码并且根本不关闭记事本(带有注释的第二次睡眠)
似乎destroy是一个异步调用(只是发送一个信号?),它会导致第二个异常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
永远不会引发异常,即使睡眠值只有1ms这是因为sleep()
开销本身吗强> 第二个exitValue
将返回1李>
另外,我在Windows7和Eclipse上运行它
# 1 楼答案
我希望destroy()方法调用本机windows函数TerminateProcess。 看着MSDN,我发现:
所以我认为它解释了破坏确实是异步的
来自同一来源的另一个摘录:
我想“无条件地”可以解释为什么对终止进程调用destroy()不会失败
希望这有帮助。(真是个有趣的问题!)
# 2 楼答案
为什么会显示出问题?你试图破坏一个已经被破坏的进程。
Process.destroy()
的规范没有说明如果没有要销毁的东西会发生什么,因此(我认为)假设如果没有要销毁的东西,那么就没有什么可抱怨的,这是合乎逻辑的。与Thread.join()
相比,如果线程已经结束,它不仅仅会消亡终止进程的唯一方法是向其发送信号。在某些操作系统上,还有其他更“暴力”的方式(例如,在某些平台上,可以简单地将进程从操作系统的运行进程列表中删除。结果没有定义,通常结局很糟糕),但至少在我所知的平台上,这实际上是关于发送信号的
确实,这可能是因为调用
Thread.sleep()
需要时间。尝试增加超时值# 3 楼答案
ProcessImpl.java
关于destroy
方法调用本机函数terminateProcess
:terminateProcess
依赖于平台,对于Windows,您可以找到源代码here。它只是用uExitCode=1
调用Windows TerminateProcess函数(指向该函数的链接在前面的答案中,或者你可以用谷歌搜索它)——这就是为什么销毁进程的退出代码是1
在linux中,似乎使用了类似于this的东西。作为证明,下一个代码在ubuntu中返回
143
,对应于SIGTERM
(https://stackoverflow.com/a/4192488/3181901):