销毁Java虚拟机线程始终运行

25

在分析我的应用程序时,我发现了一个奇怪的行为——DestroyJavaVM线程始终在运行——一直占用100%的时间。

enter image description here 在对这个主题进行一些研究后,我发现几乎没有有价值的在线信息。我所理解的是,这个线程应该在退出时卸载JVM

如果是这样,为什么这个线程从我启动我的应用程序的第一刻起就处于运行状态呢?它不会消耗宝贵的资源,因此可能会导致OutOfMemoryError(就像我有时会遇到的那样)吗?

有没有任何官方参考资料说明这个线程实际上做了什么以及是什么触发了它的初始化?

谢谢


很可能是其他线程导致了 OOME。我不会从最不明显的嫌疑人开始。您是否对应用程序线程进行了内存使用分析?这将是调试您神秘的 OOME 的直接方法。 - Kayaman
感谢您的回答。当然,我已经采取了其他措施来找出为什么会出现OOME(顺便说一下,这是“GC Overhead Limit Exceeded”错误,由高CPU使用率引起),但都没有成功。这是我的最后一招。这个线程非常可疑,我想知道它为什么要一直运行100%的时间。 - KidCrippler
2个回答

73
这是因为大多数应用程序在线程中运行。
所有POJO应用程序都通过调用main方法启动。在最简单的情况下,此方法将完成所有工作,创建对象,调用方法等。一旦main完成,JVM会使用DestroyJavaVM线程告知其关闭,并在执行其工作之前等待所有非守护线程完成。这是为了确保您创建的任何非守护线程在JVM关闭之前都能运行到完成。
然而,具有GUI的应用程序通常作为多个线程运行。一个用于监视系统事件,例如键盘或鼠标事件。一个用于维护窗口和显示等。这种应用程序的main方法可能只是启动所有所需的线程并退出。它仍然创建DestroyJavaVM线程,但现在它所做的只是等待您创建的所有线程完成后再关闭VM。
因此,任何创建线程并仅依赖其功能的应用程序都将始终有一个DestroyJavaVM线程在等待其完成。由于它只是join所有其他正在运行的线程,因此它不会消耗任何资源。

1
我的应用程序没有任何GUI界面。不过我正在实例化很多线程,并且肯定依赖于它们的功能。这是否与DestroyJavaVM线程有关?实际上是什么触发了它的初始化? 如果我理解你的意思正确,你是说即使线程显示为RUNNING,它实际上也是WAITING状态? - KidCrippler
5
@KidCrippler - 它会在 main 函数结束后创建和启动。参见 Thread.join(),了解为何它处于“运行”状态 - 它在一个紧凑循环中使用 wait(0) 方法。 - OldCurmudgeon

0

这只是皮毛。有系统触发的退出和强制退出,应用程序必须知道如何响应,而不会被非守护线程无限期地阻塞。

作为一名Java程序员,我需要知道操作系统何时告诉应用程序关闭(以便保存用户的工作)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接