我有一个启动另一个 Java 应用程序的 Java 应用程序。启动器有一个看门狗定时器,并定期接收来自第二个虚拟机的通知。但是,如果没有收到通知,则应终止第二个虚拟机,并且启动器将执行一些额外的清理活动。
问题是,有没有办法只使用java来做到这一点?到目前为止,我必须使用一些本机方法来执行此操作,而且它有点难看。
谢谢!
我有一个启动另一个 Java 应用程序的 Java 应用程序。启动器有一个看门狗定时器,并定期接收来自第二个虚拟机的通知。但是,如果没有收到通知,则应终止第二个虚拟机,并且启动器将执行一些额外的清理活动。
问题是,有没有办法只使用java来做到这一点?到目前为止,我必须使用一些本机方法来执行此操作,而且它有点难看。
谢谢!
我可能遗漏了一些东西,但你不能在返回的对象destroy()上调用方法吗?ProcessRuntime.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
}
希望这可以帮助,
肖恩
您还可以在调用 System.exit() 的第二个 JVM 上发布服务(通过粗麻布、粗麻布等)并从看门狗 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 代码在运行时检测平台并触发平台的终止进程命令。这确实是对您当前解决方案的改进。
还有Process.destroy(),如果您使用的是ProcessBuilder API
不完全是进程管理,但您可以在您正在启动的 java 虚拟机中启动一个 rmi 服务器,并将远程实例绑定到一个方法,该方法执行所需的任何清理并调用 System.exit()。然后第一个 vm 可以调用该远程方法来关闭第二个 vm。