如何强制Java进程退出热点崩溃

Pau*_*rth 5 java windows

有没有办法确保在Hotspot崩溃时整个Java进程将退出?

出于进程隔离的目的,我们在远程Windows Java进程(java.exe)中托管本机库.但是,我们发现即使存在热点崩溃,虽然主线程因热点崩溃而"死亡",但进程本身并不会死亡.我们必须在任务管理器中杀死它.

我们认为这可能是因为本机库本身创建了自己的线程,这使得进程保持活跃状态​​.

如果存在热点崩溃,我们希望整个Java进程死掉.

我们目前的工作是使用另一个线程来读取生成进程的输出(我们必须先读取控制台输出以阻止进程阻塞).我们修改它以明确查看VM崩溃:

private static String HOTSPOT_CRASH = "# A fatal error has been detected by the Java Runtime Environment";

public void run() {
    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        do {
            line = reader.readLine();
            if (line != null) {
                logger.info(prefix + ": " + line);
            }
            if(line.contains(HOTSPOT_CRASH)) {
                logger.error(String.format("FATAL Hotspot crash detected. Killing child process '%s'...", hostProcess));
                hostProcess.destroy();
            }
        } while (line != null);
        reader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

但这是一个黑客攻击:如果JVM知道足以注意到崩溃,那么如果它被告知终止当前进程会好得多.

有没有办法做到这一点?理想情况下,它将是JVM的命令行选项.

Aar*_*lla 0

通常,当检测到致命错误时,虚拟机将退出,但您可以在代码中阻止这种情况。这里有一些线索:

  • 检查父进程。在 Unix 上,只有当父进程处理信号时,子进程才会死亡SIGCHLD(这告诉父进程子进程已经终止;例如,这允许父进程读取退出代码)。

    waitFor()确保处理输出并在孩子死亡后至少调用一次。这应该清理子进程。

  • 寻找非守护线程。如果 Java 应用程序中有任何非守护线程,它们可能会阻止 VM 退出。

    但是虚拟机错误会终止所有线程,所以我的猜测是你永远不会清理子进程。