在我们的服务器上,我们开始遇到问题OutOfMemoryError
.我们使用Eclipse Memory Analysis分析了堆转储,并发现许多对象都要进行最终化(约占堆的2/3):
我们发现,它可能是一些finalize()方法阻塞.我发现了几个关于这个问题的bug报告(这里或这里),它总是在Finalizer线程堆栈中表现出来,它在某个地方被阻塞了.但在我们的例子中,这个帖子是WAITING:
"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
s 的频率减少,所以我们首先认为它有所帮助.
最后,我们怀疑JVM错误并从OpenJDK 1.6.0_30升级到Oracle JDK 1.7.0_51,问题消失了(至少看起来如此,在过去4小时内使用的堆没有增长).我们不记得finalize方法有任何变化,我们也没有升级任何库,在那段时间里只有很小的发展.问题不会在我们的测试服务器上重现,具有相同的配置,除了它是64位JVM而生产服务器是32位.
问题是:什么可能是对象没有最终确定和Finalizer
线程等待下一个对象的原因?我们是否正确分析了堆转储?
谢谢你的所有答案.