我有一个启动另一个 Java 应用程序的 Java 应用程序。启动器有一个看门狗定时器,并定期接收来自第二个虚拟机的通知。但是,如果没有收到通知,则应终止第二个虚拟机,并且启动器将执行一些额外的清理活动。
问题是,有没有办法只使用java来做到这一点?到目前为止,我必须使用一些本机方法来执行此操作,而且它有点难看。
谢谢!
我有一个启动另一个 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
}
希望这可以帮助,
肖恩
您还可以在调用 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。