0

我的應用程序運行在HotSpot jvm 1.8.0_45上,打包好的8GB堆。應用程序嘗試爲新對象分配內存失敗,併發生堆空間OOM錯誤。我查看了堆轉儲,發現大部分空間都被charCCufferCaches的T4CConnection實例佔用。這個緩存爲char數組保存了SoftReferences。我很驚訝SoftReferences在OOM之前沒有發佈。我再次檢查是否有一個這個數組的硬引用,但沒有找到一個。OOM錯誤和怪異的SoftReferences

爲什麼我的應用程序通過SoftReferences持有3GB字符數組時存在堆空間OOM? 爲什麼這個SoftReferences在應用程序需要新內存時不能發佈? T4CConnection對象的

部分表示charBufferCache:用於字符數組

part of T4CConnection object showing charBufferCache

傳入的引用在T4CConnection charBufferCache holded者:

incoming references for char array holded at T4CConnection charBufferCache

+0

什麼時候被轉儲捕獲?這可能是由於堆棧上的某些東西使數組保持活動狀態,並且由於異常導致堆棧解開後,轉儲中並未反映該數組。而且,OOM的具體類型也很重要,例如,即使釋放軟引用後分配請求可能已滿足,也可能發生超出一個的開銷。使用+ HeapDumpOnOutOfMemoryError JVM選項創建了 – the8472

+0

轉儲。我認爲這個選項產生的快照應該包含OOM錯誤出現時的所有對象和引用。快照中是否有任何參考文獻缺失的機會?另外,我的應用程序沒有通過大幀消耗內存 - 它不會一次嘗試分配2GB對象。 – nukie

+0

是的,我認爲這個選項確實包含了棧根。但OOME的確切類型仍然可能會有所作爲。 – the8472

回答

1

理想的軟的引用都應該投擲前被清除OOM。我懷疑存在一些程序內存泄漏..

你可能想看看這裏 - How to cause soft references to be cleared in Java?

嘗試-XX:SoftRefLRUPolicyMSPerMB=<value>參數限制軟引用的大小,並檢查是否有幫助。這可能會提供下一步的方向。

+0

謝謝@Anand Vaidya!我會嘗試這個選項。 – nukie

-1

只有清除對象時,纔會清除SoftReference或WeakReference。它不會阻止收集對象,但如果該對象在某處具有強引用,它將在GC之後保留。

例如

Double d = new Double(123456); 
WeakReference<Double> ref = new WeakReference<>(d); 
System.gc(); 
System.out.println(ref.get() + " == " + d); // both not null. 
+0

謝謝你,@Peter Lawrey!我明白,如果應用程序擁有強大的引用,那麼弱/弱魔法將不起作用。我已經在我的堆轉儲中搜索每個可疑SoftReferenece對象的傳入引用。我沒有發現任何參考軟件引用容器旁邊的char數組...這是我的問題的主要觀點:我有活的軟對象的引用,沒有強引用這個數組... – nukie