关于java:JVM包含监视器的线程转储而没有锁定线程

关于java:JVM包含监视器的线程转储而没有锁定线程

JVM Thread dumps containing monitors without locking threads

是什么原因导致JVM线程转储显示了等待锁定在监视器上的线程,但是监视器没有相应的锁定线程?

Windows 2003上的Java 1.5_14


这些等待线程是否一直在等待,或者它们最终会继续进行?

如果是后者,则可能是垃圾收集器锁定了该锁。

您可以在Java命令行上添加参数-verbose:gc with -XX:+PrintGCDetails,以告知发生GC的时间。如果gc活动与您的速度下降同时发生,则可能表明这是问题所在。

有关垃圾收集的一些信息。


通过任何更改,您的代码是否使用任何JNI? (即,您是否正在运行从Java启动的任何本机代码?)。

我们已经看到了类似的行为,但是JDK 1.6.0_05。 App似乎出现死锁,但是Jstack显示了线程正在等待没有其他线程持有的锁。我们有一些JNI代码,因此很可能我们正在破坏某些内容。

我们尚未找到解决方案,该问题只能在1台计算机上重现。


您是否尝试过升级到Java 1.6?如果您仅使用1.5,则可能是一个错误。


我今天有一个类似的问题,它还涉及静态资源的访问。

简短的版本是,一个类在静态块中以及在AWT-EventQueue线程之外(由AWT TreeLock阻止)在GUI内进行了GUI更改,然后EventQueue引用了被阻止的类,这迫使它进行了更改。在类加载器的监视器上等待该类。

此处的主要观察结果是类加载器的锁未在线程转储中显示为已锁定。

完整的答案可以在该线程上找到。


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

您能在哪里将转储文件上传为文本文件,以便于搜索,并告诉我们您要使用的监视器。


那只是一个疯狂的猜测,但这是否可能是线程通过尝试两次获取锁来锁定自己?如果您可以发布一些代码,可能会有所帮助。


推荐阅读