可能的原因是JVM线程转储显示线程正在等待在监视器上加锁,但是监视器没有相应的加锁线程。这种情况可能与代码中的同步块未正确释放有关。此外,还可能存在编程错误或线程死锁问题。
所述环境为Windows 2003上的Java 1.5_14版本。
所述环境为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引用了被阻塞的类,这迫使它在该类的类加载器监视器上等待。
这里的关键观察是,在线程转储中,类加载器的锁没有显示为已锁定。
完整答案可以在此线程中找到。
那只是一个猜测,但是可能是线程尝试两次获取锁而导致自己被锁住?如果您能发布一些代码可能会有所帮助。
通常情况下,每个被锁定的监视器都必须有一个所有者线程。也许您的堆栈转储不完整(太长),或者转储不一致。我可以想象它并没有停止世界,因此在转储时会转储一个被锁定的监视器,但是拥有锁的线程在被转储之前释放了它(这只是一个猜测)。
您能否在某个地方上传转储文件作为文本文件以便更轻松地搜索,并告诉我们您正在查看哪个监视器。