【问题标题】:JVM Thread dumps containing monitors without locking threadsJVM 线程转储包含没有锁定线程的监视器
【发布时间】:2010-09-09 01:30:52
【问题描述】:

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

Windows 2003 上的 Java 1.5_14

【问题讨论】:

  • 你有我们可以看到的转储吗?

标签: java multithreading


【解决方案1】:

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

我们看到了类似的行为,但 JDK 1.6.0_05。应用程序似乎死锁,但 Jstack 显示线程正在等待没有其他线程持有的锁。我们有一些 JNI 代码,所以我们可能正在破坏某些东西。

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

【讨论】:

    【解决方案2】:

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

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

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

    这里有一些information on garbage collection

    【讨论】:

    • 他们最终会在几分钟后继续。我如何确认它是否被垃圾收集器持有。我应该期望在线程转储中看到垃圾收集器线程吗?
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      您能否将转储上传为文本文件以便于搜索,并告诉我们您正在查看哪个监视器。

      【讨论】:

        【解决方案5】:

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

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

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

        完整的答案可以在on this thread找到。

        【讨论】:

          【解决方案6】:

          您是否尝试过升级到 Java 1.6?如果您仅在 1.5 上,错误可能是您的问题。

          【讨论】:

            猜你喜欢
            • 2011-10-27
            • 1970-01-01
            • 2015-09-20
            • 2021-11-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-06-16
            • 2013-12-21
            相关资源
            最近更新 更多