Java线程转储:没有"等待锁定......"的BLOCKED线程

Oli*_*ver 20 java jstack thread-dump

我很难理解我从jstack获得的在Tomcat 6上运行的Spring MVC Web应用程序的线程转储(java 1.6.0_22,Linux).

我看到阻塞线程(导致其他线程等待)自己被阻塞,但是线程转储没有告诉我为什么或者他们正在等待哪个监视器.

例:

"TP-Processor75" daemon prio=10 tid=0x00007f3e88448800 nid=0x56f5 waiting for monitor entry [0x00000000472bc000]
    java.lang.Thread.State: BLOCKED (on object monitor)
        at java.lang.Class.initAnnotationsIfNecessary(Class.java:3067)
        - locked <0x00007f3e9a0b3830> (a java.lang.Class for org.catapultframework.resource.ResourceObject)
        at java.lang.Class.getAnnotation(Class.java:3029)
        ...
Run Code Online (Sandbox Code Playgroud)

即我错过了堆栈跟踪中的"等待锁定..."行.显然线程锁定了一个Class对象,但是我不明白为什么线程本身被阻塞了.

线程转储不包含任何死锁提示.

如何识别锁定监视器?

谢谢,奥利弗

Oli*_*ver 10

显然,我们观察到这些被阻塞的线程的情况与大量内存消耗和大量垃圾收集有关.

这个问题Java阻塞问题:为什么JVM会在许多不同的类/方法中阻塞线程?描述了类似的情况,所以我相信这些线程只是被垃圾收集器阻止了.

(无论如何,在解决了内存问题后,阻塞线程的问题就消失了.)


use*_*655 5

检查终结器线程是否被阻止或正在等待。

在GC扫描期间,GC将“停止运行”以执行其清理。“世界”的定义取决于所使用的垃圾收集器和上下文。它可能是一小群线程或所有线程。在正式收集垃圾之前,GC将调用对象的finalize()。

如果您在实现终结器方法的不受欢迎的情况下,终结代码可能会阻止其完成,并且“世界”将停止。

当看到许多线程被某种未知的魔术力永久阻塞时,这是最明显的:查找发生阻塞的代码,这没有任何意义;在它附近的任何地方都找不到阻塞代码,并且转储不会泄露它正在等待的监视器,因为没有监视器。GC已暂停线程。