5

我在使用 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 重新启动之前,线程会一直卡住。

谁能给我一个关于这里发生了什么的想法,什么可能导致本机方法阻塞?每个卡住的线程顶部的监视器入口地址范围是不同的。我怎样才能弄清楚这个显示器是什么?

任何建议或意见将不胜感激!

谢谢,大卫

4

5 回答 5

4

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

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

我会进一步调查类加载明智的情况。也许某些线程使用类加载器从网络位置加载一个类,该位置速度很慢/不可用,因此阻塞了很长时间,而不是将监视器让给想要加载类的其他线程。使用 -verbose:class 启动 JVM 时调查输出可能是一件事。

于 2008-09-30T10:50:43.080 回答
2

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

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

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

于 2008-10-01T05:50:50.283 回答
1

你能找出哪个线程在本机方法正在等待的监视器上实际同步吗?至少当您向 VM 发送 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)

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

于 2008-10-07T10:19:34.533 回答
0

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

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

于 2011-02-15T15:41:30.270 回答
0

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

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

于 2008-09-01T19:22:39.293 回答