在我們的服務器上,我們開始遇到OutOfMemoryError
問題。我們分析了堆轉儲使用Eclipse內存分析和發現,許多對象舉行做最後定稿(約堆的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
S中的頻率減少,因此,我們首先想到的幫助。最後,我們懷疑JVM的bug,並且從OpenJDK 1.6.0_30升級到了Oracle JDK 1.7.0_51,問題消失了(至少看起來如此,在過去的4個小時中,使用的堆不會增長)。我們不記得定稿方法有什麼變化,我們也沒有升級任何圖書館,在那段時間只有小的發展。這個問題不會在我們的測試服務器上重現,具有相同的配置,只是它是64位JVM,而生產服務器是32位。
現在的問題是:什麼原因可能導致對象未完成並且Finalizer
線程正在等待下一個對象?我們是否正確分析了堆轉儲?
感謝您的所有答案。
你的終結者線程正在等待某個東西被終結(它在'ReferenceQueue.remove()'上被阻塞),這意味着沒有任何對象要被終結。你是怎麼得出這個結論是'finalize()'方法阻塞的?你是否在代碼中積極使用'finalize()'? – Kayaman
@Kayaman通過分析堆轉儲,請參見圖片 – Oliv