JVM 线程转储显示线程等待锁定在监视器上的原因可能是什么,但监视器没有相应的锁定线程?
Windows 2003 上的 Java 1.5_14
您的代码是否通过任何更改使用任何 JNI?(即,您是否正在运行从 Java 启动的任何本机代码?)。
我们已经看到了类似的行为,但是 JDK 1.6.0_05。应用程序似乎死锁,但 Jstack 显示线程正在等待没有其他线程持有的锁。我们有一些 JNI 代码,所以我们可能正在破坏某些东西。
我们还没有找到解决方案,这个问题只能在一台机器上重现。
那些等待的线程是永远等待,还是最终会继续?
如果是后者,则可能是垃圾收集器持有该锁。
您可以在您的 java 命令行上添加参数-verbose:gc with -XX:+PrintGCDetails
,以便在 GC 发生时被告知。如果 gc 活动与您的减速一致,则可能表明这是问题所在。
这是有关垃圾收集的一些信息。
是的,通常每个被锁定的监视器都必须有一个所有者线程。也许您的堆栈转储不完整(太长)或者转储不一致。我可以想象它并没有停止世界,所以一个锁定的监视器被转储但拥有锁的线程在被转储之前释放它(这只是一个猜测)。
您能否将转储上传为文本文件以便于搜索,并告诉我们您正在查看哪个监视器。
这只是一个疯狂的猜测,但有没有可能是线程通过尝试两次获取锁来锁定自己?如果您可以发布一些代码,可能会有所帮助。
我今天也遇到了类似的问题,也涉及到静态资源的访问。
简短的版本是一个类在静态块中进行了 GUI 更改,并且在 AWT-EventQueue 线程之外,被 AWT TreeLock 阻塞,然后 EventQueue 引用了被阻塞的类,这迫使它等待该类的类加载器的监视器。
这里的关键观察是类加载器的锁在线程转储中没有显示为锁定。
完整的答案可以在这个线程上找到。
您是否尝试过升级到 Java 1.6?如果您仅使用 1.5,则错误可能是您的问题。