4

我有一个启动另一个 Java 应用程序的 Java 应用程序。启动器有一个看门狗定时器,并定期接收来自第二个虚拟机的通知。但是,如果没有收到通知,则应终止第二个虚拟机,并且启动器将执行一些额外的清理活动。

问题是,有没有办法只使用java来做到这一点?到目前为止,我必须使用一些本机方法来执行此操作,而且它有点难看。

谢谢!

4

9 回答 9

6

我可能遗漏了一些东西,但你不能在返回的对象destroy()上调用方法吗?ProcessRuntime.exec()

于 2008-09-15T15:24:49.043 回答
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
}

希望这可以帮助,

肖恩

于 2008-09-15T15:42:10.263 回答
2

您还可以在调用 System.exit() 的第二个 JVM 上发布服务(通过粗麻布、粗麻布等)并从看门狗 JVM 中使用它。如果您只想在第二个 JVM 停止发送这些定期通知时将其关闭,则它可能无法响应服务调用。

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

于 2008-09-15T15:26:00.863 回答
2

执行此操作的常用方法是调用Process.destroy()... 但是它是一个不完整的解决方案,因为在 *nix 上使用 sun JVM 时会破坏映射到不能保证终止进程的 SIGTERM(因为您也需要 SIGKILL)。最终结果是您无法使用 Java 进行真正的流程管理。

关于这个问题有一些未解决的错误,请参阅: 链接文本

于 2008-09-17T08:30:36.137 回答
1

java.lang.ProcesswaitFor()等待进程死亡的destroy()方法,以及杀死子进程的方法。

于 2008-09-15T15:47:58.707 回答
1

好的,要点如下:

我正在使用 Process API 关闭第二个虚拟机,但它不起作用。

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

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

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

我想我得去上班了。

于 2008-09-17T07:17:22.363 回答
0

你应该能够做到这一点java.lang.Runtime.exec和 shell 命令。

于 2008-09-15T15:14:01.673 回答
0

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

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

于 2008-09-15T15:17:24.537 回答
0

不完全是进程管理,但您可以在您正在启动的 java 虚拟机中启动一个 rmi 服务器,并将远程实例绑定到一个方法,该方法执行所需的任何清理并调用 System.exit()。然后第一个 vm 可以调用该远程方法来关闭第二个 vm。

于 2008-09-15T15:29:14.837 回答