什么会导致 Java 在 System.exit() 之后继续运行?

2022-09-01 13:13:55

我有一个Java程序,它是从另一个Java程序启动的。 是从子程序调用的,但对于我们的某些用户(在Windows上),与子程序关联的进程不会终止。子程序没有关机挂钩,也没有可能停止终止 VM 的挂钩。我无法在Linux或Windows Vista上自己重现问题。到目前为止,该问题的唯一报告来自两个Windows XP用户和一个Vista用户,使用两个不同的JRE(1.6.0_15和1.6.0_18),但他们每次都能够重现问题。ProcessBuilderSystem.exit(0)java.exeSecurityManagerSystem.exit()

谁能提出为什么JVM在之后无法终止的原因,然后仅在某些机器上终止?System.exit()

编辑 1:我让用户安装JDK,以便我们可以从有问题的VM中获取线程转储。用户告诉我的是,一旦他单击菜单中的“退出”项,VM进程就会从VisualVM中消失---但是,根据Windows任务管理器的说法,该进程尚未终止,无论用户等待多长时间(几分钟,几小时),它永远不会终止。

编辑 2:我现在已经确认,在父程序中,至少有一个用户遇到问题永远不会返回。所以,总结一下:子VM似乎已经死了(VisualVM甚至没有看到它),但父级仍然认为该进程是实时的,Windows也是如此。Process.waitFor()


答案 1

如果您的代码(或您使用的库)具有关闭挂钩或未完成的终结器,则可能会发生这种情况。

一种更有力的(因此应该只在极端情况下使用!)强制关机的方法是运行:

Runtime.getRuntime().halt(0);

答案 2

父进程有一个线程专用于使用每个子进程的 STDOUT 和 STDERR(它将该输出传递到日志文件)。据我所知,这些都正常工作,因为我们看到了我们希望在日志中看到的所有输出。

当我使用stdout / stderr时,我的程序没有从任务mgr中消失,我有一个类似的问题。在我的情况下,如果我在调用system.exit()之前关闭了正在收听的流,那么javaw.exe就会徘徊。奇怪,它没有写到流中...

在我的情况下,解决方案是简单地冲洗流,而不是在存在之前关闭它。当然,您可以随时冲洗,然后在退出之前重定向回stdout和stderr。


推荐