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

4
我有一个Java应用程序,它启动另一个Java应用程序。启动器具有看门狗计时器,并从第二个VM接收定期通知。但是,如果没有接收到通知,则应杀死第二个虚拟机,启动器将执行一些额外的清理活动。
问题是,是否有办法仅使用Java来实现此操作?到目前为止,我必须使用一些本地方法来执行此操作,这有点丑陋。
谢谢!
9个回答

6

3
你可以使用 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
}

希望这能帮到你,
Sean

2
通常的做法是调用Process.destroy()... 然而这只是一个不完整的解决方案,因为当在*nix上使用sun JVM时,destroy映射到一个SIGTERM,不能保证终止进程(需要同时使用SIGKILL)。结果是你无法使用Java进行真正的进程管理。
关于这个问题有一些未解决的bug,请参见: 链接文本

2
您还可以在第二个JVM上发布一个服务(通过burlap,hessian等),调用System.exit()并从监视JVM中消耗它。 如果你只想在第二个JVM停止发送那些定期通知时关闭它,可能无法处于响应服务调用的状态。
使用java.lang.Runtime.exec()调用shell命令可能是您最好的选择。

1

好的,这件事的关键在于:

我使用了进程 API 关闭第二个虚拟机,但是它不起作用。

原因是我的第二个应用程序是 Eclipse RCP 应用程序,并且是使用包含在其中的 eclipse.exe 启动器启动的。

然而,这意味着 Process API 的 destroy() 方法将针对 eclipse.exe 进程。杀死此进程不会影响 Java 进程。所以,我的一位同事编写了一个小应用程序来关闭正确的应用程序。

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

我想我得开始工作了。


1

java.lang.Process类有一个waitFor()方法,用于等待进程结束,还有一个destroy()方法,用于杀死子进程。


0

您应该能够使用java.lang.Runtime.exec和shell命令来完成此操作。


0

你可以让Java代码在运行时检测平台并触发平台的终止进程命令。这实际上是对你当前解决方案的改进。

如果你正在使用ProcessBuilder API,也可以使用Process.destroy()


0

虽然不完全是进程管理,但您可以在启动的Java虚拟机中启动RMI服务器,并绑定一个remote实例,该实例具有执行所需清理并调用System.exit()的方法。第一个虚拟机随后可以调用该远程方法来关闭第二个虚拟机。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接