是否可以从另一个虚拟机中杀死一个 Java 虚拟机?
-
09-06-2019 - |
题
我有一个 Java 应用程序,它启动另一个 Java 应用程序。启动器有一个看门狗计时器,并从第二个虚拟机接收定期通知。但是,如果没有收到通知,则应终止第二个虚拟机,并且启动器将执行一些额外的清理活动。
问题是,有没有办法只使用java来做到这一点?到目前为止,我必须使用一些本机方法来执行此操作,这在某种程度上很难看。
谢谢!
解决方案
我可能错过了一些东西,但你不能打电话给 destroy()
方法上的 Process
返回的对象 Runtime.exec()
?
其他提示
您可以使用 java.lang.Process 做你想做的事。创建嵌套流程并拥有对 Process 实例的引用后,您就可以获得对其标准输出流和错误流的引用。您可以定期监视这些进程,如果您想关闭进程,则可以调用 .destroy() 。整个事情可能看起来像这样:
Process nestedProcess = new ProcessBuilder("java mysubprocess").start();
InputStream nestedStdOut = nestedProcess.getInputStream(); //kinda backwards, I know
InputStream nestedStdErr = nestedProcess.getErrorStream();
while (true) {
/*
TODO: read from the std out or std err (or get notifications some other way)
Then put the real "kill-me" logic here instead of if (false)
*/
if (false) {
nestedProcess.destroy();
//perform post-destruction cleanup here
return;
}
Thread.currentThread().sleep(1000L); //wait for a bit
}
希望这可以帮助,
肖恩
您还可以在第二个 JVM 上发布一个服务(通过 burlap、hessian 等),该服务调用 System.exit() 并从看门狗 JVM 中使用它。如果您只想在第二个 JVM 停止发送这些定期通知时将其关闭,它可能不会处于响应服务调用的状态。
使用 java.lang.Runtime.exec() 调用 shell 命令可能是您最好的选择。
通常的方法是调用 Process.destroy()...然而,这是一个不完整的解决方案,因为在 *nix 上使用 sun JVM 时,销毁映射到 SIGTERM,这不能保证终止进程(为此您还需要 SIGKILL)。最终结果是您无法使用 Java 进行真正的流程管理。
关于此问题有一些未解决的错误,请参阅:链接文本
java.lang.Process 有一个 waitFor() 方法来等待进程死亡,还有一个 destroy() 方法来杀死子进程。
好的,要点如下:
我使用 Process API 关闭第二个虚拟机,但它不起作用。
原因是我的第二个应用程序是 Eclipse RCP 应用程序,我使用附带的 eclipse.exe 启动器启动它。
但是,这意味着 Process API destroy() 方法将针对 eclipse.exe 进程。终止该进程不会使 Java 进程受到损害。因此,我的一位同事编写了一个小应用程序,它将杀死正确的应用程序。
因此,使用 Process API(并删除多余的中间步骤)的解决方案之一是摆脱 Eclipse 启动器,让我的第一个虚拟机复制其所有功能。
我想我得去上班了。
您应该能够执行 java.lang.Runtime.exec 和 shell 命令。
您可以让 java 代码在运行时检测平台并触发平台的终止进程命令。这实际上是对您当前解决方案的改进。
还有 进程.destroy(), ,如果您正在使用 流程构建器 应用程序编程接口
不完全是进程管理,但你可以在你正在启动的java虚拟机中启动一个rmi服务器,并绑定一个 偏僻的 具有执行所需清理操作并调用 System.exit() 的方法的实例。然后,第一个虚拟机可以调用该远程方法来关闭第二个虚拟机。