JVM 不会终止
我对一些中等复杂度的代码进行了简单的测试运行,这些代码不会终止,即主方法完成但进程不会终止。
以下是代码的概要(代码太长,无法粘贴到此处):
ProcessBuilder
用于创建一堆子流程。它们都会正常死亡(如果你相信 VisualVM)。- 我们使用log4j。
- 主要算法在
FutureTask
内运行,在该FutureTask 上调用run
和稍后的get
。 - 我们没有明确使用 RMI,尽管线程列表似乎表明如此。
显然,我可以调用 System.exit(0)
,但我想知道这里出了什么问题。我无法给出一个最小的失败例子。另外,我无法从线程列表中识别出明显的罪魁祸首;也许你可以?
编辑: 请参阅此处 获取线程转储。
I have a simple test run of some medium-complexity code that won't terminate, i.e. the main method finishes but the process does not die.
Here is a rundown of the code (which is too long to be pasted here):
ProcessBuilder
is used to create a bunch of subprocesses. They all die properly (if you can believe VisualVM).- We use log4j.
- The main algorithm runs inside a
FutureTask
on whichrun
and laterget
are called. - We don't explicitly use RMI, even though the list of threads seems to suggest so.
Obviously, I can call System.exit(0)
, but I'd like to know what is amiss here. I have not been able to produce a minimum failing example. Also, I can not identify an obvious culprit from the thread list; maybe you can?
Edit: See here for a thread dump.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Scorpion 引导我找到了正确的答案:
RMI Reaper
类似于远程对象的垃圾收集器,例如UnicastRemoteObject
(的子类)的实例。它是一个非守护线程,因此如果仍然存在无法清理的导出对象,则会阻止 JVM 终止。您可以通过将远程对象传递给
UnicastRemoteObject.unexportObject(., true)
来明确强制清理远程对象。如果您对所有先前导出的对象执行此操作,RMI Reaper
将终止并且 JVM 可以自由关闭。Scorpion lead me to the right answer:
RMI Reaper
is something like a garbage collector for remote objects, e.g. instances of (subclasses of)UnicastRemoteObject
. It is a non-daemon thread and therefore blocks JVM termination if there are still exported objects which can not be cleaned up.You can explicity force remote objects to be cleaned up in this sense by passing them to
UnicastRemoteObject.unexportObject(., true)
. If you do this on all previously exported objects,RMI Reaper
terminates and JVM is free to shut down.你提到了FutureTask。我首先想到的是:您是否在使用 ExecutorService 却忘记关闭它?
我想到的第二件事是:您是否将进程中的所有流读到底?我很久以前就使用过子流程,我记不太清楚了,但是。我遇到了与您所描述的类似的问题,通过阅读流到底,问题会神秘地消失!
You mention FutureTask. The first thing that comes to my mind is: are you using ExecutorService and forgetting to shut it down?
The second thing that comes to my mind is: are you reading to the end all the streams from the process? I worked with subprocesses long ago, and I don't remember exactly, but. I had problems similar to what you described, and by reading the streams to the end the problem would misteriously disappear!