如果有热点崩溃,有没有办法确保整个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();
}
}
但这是一个黑客行为:如果JVM知道足以注意到崩溃,那么如果可以告诉它终止当前进程会更好。
有没有办法做到这一点?理想情况下,它将是JVM的命令行选项。
答案 0 :(得分:0)
通常,当检测到致命错误时,VM将退出,但您可以在代码中阻止此操作。以下是一些线索:
检查父进程。在Unix上,子进程只能在父进程处理SIGCHLD
信号时(它告诉父进程已终止子进程;这允许父进程读取退出代码)。
确保您处理输出并在孩子死后至少调用waitFor()
一次。这应该清理孩子的过程。
查找非守护程序线程。如果Java应用程序中有任何非守护程序线程,则可以阻止VM退出。
但VM错误将终止所有线程,所以我猜你永远不会清理子进程。