在我们的服务器上,我们开始遇到 OutOfMemoryError
问题。我们使用 Eclipse Memory Analysis 分析了堆转储,发现有许多对象被保留以进行终结(大约占堆的 2/3):
我们发现,它可能是一些 finalize() 方法阻塞。我发现了几个关于这个问题的错误报告(here 或 here),它总是在 Finalizer 线程堆栈中表现出来,它在某处被阻塞。但在我们的例子中,这个线程正在等待:
"Finalizer" daemon prio=10 tid=0x43e1e000 nid=0x3ff in Object.wait() [0x43dfe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x4fe053e8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133)
- locked <0x4fe053e8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)
编辑:
然后我们尝试添加 -XX:+UseConcMarkSweepGC
,但没有成功,只是 OutOfMemoryError
的频率减少了,所以我们首先认为它有所帮助。
最后,我们怀疑是 JVM bug,从 OpenJDK 1.6.0_30 升级到 Oracle JDK 1.7.0_51,问题消失了(至少看起来是这样,在过去的 4 小时内,使用的堆没有增长)。我们不记得 finalize 方法有任何变化,也没有升级任何库,在那段时间只有很小的发展。该问题不会在我们的测试服务器上重现,配置相同,除了它是 64 位 JVM 而生产服务器是 32 位。
问题是:什么可能导致对象未被最终化和 Finalizer
线程等待下一个对象?我们是否正确分析了堆转储?
谢谢大家的回答。
最佳答案
我们认为它与 OpenJDK 1.6.0_30 版本有关。升级到Oracle JDK 1.7.0_51后,问题消失。而且应该是openJDK自动更新后出现的,但我们也无法确认。我们找不到相关的错误报告。
关于java - 对象未被终结且 Finalizer 线程未执行任何操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22243487/