我一直在试验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()
调用在尝试停止已终止的进程时未显示任何问题。的为什么吗 似乎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
永远不会抛出异常,即使睡眠值仅为1毫秒。 是因为sleep()
开销本身吗?
第二个exitValue
将返回1. PS。我从Windows 7和Eclipse运行它。
答案 0 :(得分:1)
我期望destroy()方法调用本机windows函数TerminateProcess。 看MSDN,我发现了这个:
TerminateProcess是异步的;它启动终止并立即返回。如果您需要确保进程已终止,请使用该进程的句柄调用WaitForSingleObject函数。
所以我认为它解释了破坏确实是异步的。
来自同一来源的另一个摘录:
TerminateProcess函数用于无条件地导致进程退出。
我想“无条件”可以解释为什么对终止进程的destroy()调用不会失败。
希望这有帮助。 (非常有趣的问题!)
答案 1 :(得分:1)
为什么会显示问题?你正试图摧毁一个已被破坏的进程。 Process.destroy()
的规范没有说明如果没有什么可以破坏会发生什么,所以我认为如果没有什么可以破坏那么合乎逻辑(我猜)就没有什么可抱怨的了。与Thread.join()
比较,如果线程已经结束,它不会死亡。
杀死进程的唯一方法是向其发送信号。在某些操作系统上,还有其他更“暴力”的方式(例如,在某些平台上,可以简单地从操作系统的正在运行的进程列表中删除该进程。结果未定义且通常结束很难看),但至少对于我所知道的平台,它实际上就是发送信号。
确实可能是因为调用Thread.sleep()
需要时间。尝试增加超时值。
答案 2 :(得分:1)
ProcessImpl.java
方法调用本机函数destroy
上的 terminateProcess
:
public void destroy() { terminateProcess(handle); }
private static native void terminateProcess(long handle);
terminateProcess
取决于平台,对于Windows,您可以找到来源here。它只是通过uExitCode=1
调用Windows TerminateProcess函数(此函数的链接在以前的答案中,或者你可以google) - 这就是为什么退出的进程代码是1
。
在linux中看起来像使用类似于this的东西。作为证明,下一个代码在ubuntu中返回143
,对应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());
}