JVM线程转储包含未锁定线程的监视器

8
可能的原因是JVM线程转储显示线程正在等待在监视器上加锁,但是监视器没有相应的加锁线程。这种情况可能与代码中的同步块未正确释放有关。此外,还可能存在编程错误或线程死锁问题。
所述环境为Windows 2003上的Java 1.5_14版本。

你有我们可以看到的转储文件吗? - svrist
6个回答

1

你的代码是否使用了JNI?(即,你是否在Java中运行任何本地代码?)

我们曾经遇到过类似的情况,但是在JDK 1.6.0_05上。应用程序似乎发生了死锁,但是Jstack显示线程正在等待一个没有其他线程持有的锁。我们有一些JNI代码,所以有可能我们破坏了某些东西。

我们还没有找到解决方案,而且这个问题只在一台机器上复现。


1

那些等待的线程会永远等待,还是最终会继续执行?

如果是后者,可能是垃圾回收器持有了锁。

您可以在Java命令行中添加参数-verbose:gc with -XX:+PrintGCDetails,以便在发生GC时得到通知。如果GC活动与您的减速同时发生,则可能表明这是问题所在。

这里有一些关于垃圾回收的信息


它们最终会在几分钟后继续执行。我如何确认它是否被垃圾回收器持有?我应该期望在线程转储中看到垃圾回收器线程吗? - Kevin

0

我今天遇到了类似的问题,也涉及静态资源的访问。

简而言之,一个类在静态块中做了GUI更改,而且不是在AWT-EventQueue线程外部,这些更改被AWT TreeLock阻塞,然后EventQueue引用了被阻塞的类,这迫使它在该类的类加载器监视器上等待。

这里的关键观察是,在线程转储中,类加载器的锁没有显示为已锁定。

完整答案可以在此线程中找到。


0
你尝试过升级到Java 1.6吗?如果你只使用1.5,可能是一个bug导致的问题。

0

那只是一个猜测,但是可能是线程尝试两次获取锁而导致自己被锁住?如果您能发布一些代码可能会有所帮助。


0

通常情况下,每个被锁定的监视器都必须有一个所有者线程。也许您的堆栈转储不完整(太长),或者转储不一致。我可以想象它并没有停止世界,因此在转储时会转储一个被锁定的监视器,但是拥有锁的线程在被转储之前释放了它(这只是一个猜测)。

您能否在某个地方上传转储文件作为文本文件以便更轻松地搜索,并告诉我们您正在查看哪个监视器。


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