是否可以从另一个虚拟机中杀死Java虚拟机?

时间:2020-03-05 18:53:40  来源:igfitidea点击:

我有一个Java应用程序,可以启动另一个Java应用程序。启动器具有看门狗计时器,并从第二个VM接收定期通知。但是,如果未收到通知,则第二台虚拟机应被杀死,启动器将执行一些其他清理活动。

问题是,有什么方法可以仅使用java来做到这一点?到目前为止,我必须使用一些本机方法来执行此操作,而且这种方法很难看。

谢谢!

解决方案

回答

我们应该能够执行java.lang.Runtime.exec和shell命令。

回答

我们可以让Java代码在运行时检测平台并启动平台的kill process命令。这实际上是对我们当前解决方案的改进。

如果我们使用的是ProcessBuilder API,则还有Process.destroy()

回答

我可能缺少了一些东西,但是我们不能在Runtime.exec()返回的Process对象上调用destroy()方法吗?

回答

我们还可以在第二个JVM上发布服务(通过粗麻布,粗麻布等),该服务调用System.exit()并从看门狗JVM使用它。如果我们只想在第二个JVM停止发送那些定期通知时将其关闭,则它可能未处于响应服务调用的状态。

用java.lang.Runtime.exec()调用shell命令可能是最好的选择。

回答

不完全是过程管理,但是我们可以在正在启动的Java虚拟机中启动rmi服务器,并使用执行所需清理操作并调用System.exit()的方法绑定远程实例。然后,第一个虚拟机可以调用该远程方法来关闭第二个虚拟机。

回答

我们可以使用java.lang.Process进行所需的操作。创建嵌套流程并获得对Process实例的引用后,就可以获取对其标准out和err流的引用。我们可以定期监视它们,如果要关闭该过程,请调用.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
}

希望这可以帮助,

肖恩

回答

java.lang.Process有一个waitFor()方法来等待进程终止,而用destroy()方法来杀死子进程。

回答

确定要点如下:

我正在使用Process API关闭第二个虚拟机,但是无法正常工作。

原因是我的第二个应用程序是Eclipse RCP应用程序,我使用附带的eclipse.exe启动器启动了它。

但是,这意味着Process API destroy()方法将以eclipse.exe进程为目标。终止此进程将毫发无损。因此,我的一位同事在这里编写了一个小型应用程序,它将杀死正确的应用程序。

因此,使用Process API(并删除多余的中间步骤)的解决方案之一就是放弃Eclipse启动器,让我的第一台虚拟机复制其所有功能。

我想我必须去上班。

回答

通常的方法是调用Process.destroy()...,但这是一个不完整的解决方案,因为在* nix上使用sun JVM时,将映射映射到SIGTERM上并不能保证终止进程(为此,我们需要SIGKILL)。最终结果是我们无法使用Java进行真正的流程管理。

关于此问题有一些未解决的错误,请参见:
连结文字