多线程卡在本机调用中(Java)

时间:2008-09-01 07:01:35

标签: java multithreading native-methods blocked

我在使用JDK 1.5.0_08的Fedora Core 6上运行应用程序时遇到问题。

经过一段时间(通常是几天)后,线程开始陷入原生方法。

线程被锁定在这样的东西:

"pool-2-thread-2571" prio=1 tid=0x08dd0b28 nid=0x319e waiting for monitor entry [0xb91fe000..0xb91ff7d4]
at java.lang.Class.getDeclaredConstructors0(Native Method)

"pool-2-thread-2547" prio=1 tid=0x75641620 nid=0x1745 waiting for monitor entry [0xbc7fe000..0xbc7ff554]
at sun.misc.Unsafe.defineClass(Native Method)

特别令我困惑的是这个:

"HealthMonitor-10" daemon prio=1 tid=0x0868d1c0 nid=0x2b72 waiting for monitor entry [0xbe5ff000..0xbe5ff4d4]
at java.lang.Thread.dumpThreads(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1383)

在VM重新启动之前,线程一直处于停滞状态。

任何人都可以告诉我这里发生了什么,可能导致本机方法阻塞的原因是什么? 每个卡住线程顶部的监视器入口地址范围不同。我怎么能弄清楚拿着这台显示器的是什么?

非常感谢任何建议或建议!

谢谢, 大卫

5 个答案:

答案 0 :(得分:4)

我最初的怀疑是你正在经历某种类加载器实现的死锁。我想,类加载需要在某个级别进行同步,因为类信息将可用于整个VM,而不仅仅是最初加载它的线程。

堆栈顶部的方法是本机方法的事实似乎是纯粹的巧合,因为类加载机制的一部分碰巧以这种方式实现。

我会进一步调查类加载的内容。也许某些线程使用类加载器从一个缓慢/不可用的网络位置加载一个类,因此阻塞很长时间,而不是让监视器到其他想要加载类的线程。使用-verbose:class启动JVM时调查输出可能是一回事。

答案 1 :(得分:2)

几个月前我遇到过类似的问题,并发现jthread(?)实用程序非常宝贵。您为它提供了Java应用程序的进程ID,它将为您的进程中的每个线程转储整个堆栈。

从jthread的输出中,我可以看到一个线程在进入监视器后尝试获取锁定,另一个线程在获取锁定后尝试进入监视器。僵局的秘诀。

我还想知道你的应用程序是否遇到了垃圾收集问题。你说它在它停止之前运行了几天。你有多久让它处于卡住状态,看看GC是否能完成?

答案 2 :(得分:1)

你能找出在本机方法等待的监视器上实际正在同步的线程吗? 至少你发送一个SIGQUIT(kill -3)时从VM获得的线程转储应该显示这个信息,如

"Thread-0" prio=5 tid=0x0100b060 nid=0x84c000 waiting for monitor entry [0xb0c8a000..0xb0c8ad90]
    at Deadlock$1.run(Deadlock.java:8)
    - waiting to lock <0x255e5b38> (a java.lang.Object)
...
"main" prio=5 tid=0x01001350 nid=0xb0801000 waiting on condition [0xb07ff000..0xb0800148]
    at java.lang.Thread.sleep(Native Method)
    at Deadlock.main(Deadlock.java:21)
- locked <0x255e5b38> (a java.lang.Object)

在目前为止发布的转储中,我看不到任何实际等待锁定特定监视器的线程......

答案 3 :(得分:0)

也许你应该使用另一个jdk版本 对于你的“令人费解的”,有一个1.5.0_08的错误条目。报告内存泄漏(我不知道,如果这与您的问题有关):
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6469701

此外,您可以获取源代码并查看,第1383行会发生什么。另一方面,它可能只是原始错误发生后的堆栈转储。

答案 4 :(得分:0)

我在遇到同样的问题后找到了这个线程 - 在Linux上使用Tomcat 6.0.29运行JDK 1.6.0_23。但是不确定这些位是否相关 - 我注意到的是,除了许多线程在getDeclaredConstructors()本机方法中“卡住”之外,java进程的CPU为100%。因此,所有请求线程都被卡在这里,CPU处于100%,线程转储没有显示任何死锁(并且没有其他线程执行任何重要活动),它闻起来像一个颠簸的垃圾收集器给我。果然,检查了服务器日志,并且出现了大量的OutOfMemory错误 - 堆空间已经耗尽。

不能说这会是线程每次都卡在这里的根本原因,但希望这里的信息能帮助其他人至少排除这个可能的原因......