我有一个Java应用程序,它启动另一个Java应用程序。启动器具有看门狗计时器,并从第二个VM接收定期通知。但是,如果没有接收到通知,则应杀死第二个虚拟机,启动器将执行一些额外的清理活动。
问题是,是否有办法仅使用Java来实现此操作?到目前为止,我必须使用一些本地方法来执行此操作,这有点丑陋。
谢谢!
问题是,是否有办法仅使用Java来实现此操作?到目前为止,我必须使用一些本地方法来执行此操作,这有点丑陋。
谢谢!
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
}
Process.destroy()
... 然而这只是一个不完整的解决方案,因为当在*nix上使用sun JVM时,destroy映射到一个SIGTERM,不能保证终止进程(需要同时使用SIGKILL)。结果是你无法使用Java进行真正的进程管理。好的,这件事的关键在于:
我使用了进程 API 关闭第二个虚拟机,但是它不起作用。
原因是我的第二个应用程序是 Eclipse RCP 应用程序,并且是使用包含在其中的 eclipse.exe 启动器启动的。
然而,这意味着 Process API 的 destroy() 方法将针对 eclipse.exe 进程。杀死此进程不会影响 Java 进程。所以,我的一位同事编写了一个小应用程序来关闭正确的应用程序。
因此,使用 Process API(并消除多余的中间步骤)的一个解决方案是摆脱 Eclipse 启动器,让我的第一个虚拟机复制其所有功能。
我想我得开始工作了。
java.lang.Process
类有一个waitFor()
方法,用于等待进程结束,还有一个destroy()
方法,用于杀死子进程。
您应该能够使用java.lang.Runtime.exec
和shell命令来完成此操作。
你可以让Java代码在运行时检测平台并触发平台的终止进程命令。这实际上是对你当前解决方案的改进。
如果你正在使用ProcessBuilder API,也可以使用Process.destroy()。
虽然不完全是进程管理,但您可以在启动的Java虚拟机中启动RMI服务器,并绑定一个remote实例,该实例具有执行所需清理并调用System.exit()的方法。第一个虚拟机随后可以调用该远程方法来关闭第二个虚拟机。