2010-09-28 53 views
0

我們收集了隨着時間推移增長得相當大的對象。我們實施了緩存策略來幫助緩解這一問題,但是,如果在啓動時沒有分配足夠的內存,我們仍然會在運行時耗盡堆空間。動態分配緩存大小以緩解堆空間錯誤

是否有標準的機制來減少運行時緩存的大小以消除這些OutOFMemory錯誤?這樣,如果我們的進程以比正常情況更小的內存片開始,我們可以希望避免服務器死機。

我意識到這是一個錯誤類型,因此不應該被捕獲/處理,因爲它通常表示更嚴重的問題。

是它具有一些如下的簡單:

private static final long RECOMMENDED_MEMORY = 1073741824L; //Example 1 Gig 
private static int recommendedCacheSize = 100; //Example of 100 items 
long heapSize = Runtime.getRuntime().totalMemory(); 
double size = Math.floor((double) heapSize/RECOMMENDED_MEMORY * recommendedCacheSize); 
recommendedCacheSize = ++size; 
+0

注意:這是在Tomcat中運行。 – Scott 2010-09-28 14:31:52

+0

緩存是使用軟參考還是弱參考構建的? – 2010-09-28 14:41:34

回答

0

爲什麼不使用被設計爲real cache的東西?

儘管可以使用軟引用來實現對內存敏感的緩存,但這種緩存往往會使對象在內存中保留太久(增加GC負載)。弱引用不適用於緩存,因爲它們被清除的可能性要高得多(實際上,每個GC都會清除它們)。

0

我懷疑緩存實現不保持WeakReferenceSoftReference對象,它們在一個Java對象緩存通常採用的緩存。對緩存使用軟或弱引用是非常重要的,否則就有可能引發OOME(內存不足錯誤)。

使用軟/弱引用的理由是垃圾收集器將嘗試收集這些對象,以防內存不足。使用強引用(普通對象引用)來存儲對緩存中對象的引用,將會阻止內存被回收。

但是,即使您使用弱/軟引用,您也會得到OOME,我懷疑您的GC沒有很好地調整。看起來您的應用程序會突然遇到內存消耗,導致OOME狀況。這種情況是不太可能的,但是可能的,特別是如果先前調用GC沒有清除足夠的內存(最終消耗在下一次消耗中)。

+0

我們的對象緩存正在使用Apache Commons KeyedObjectPool,所以我們應該符合這個標準。我相信我們的默認設置太高的真正問題。這個想法是允許每個開發人員根據他們機器的每一種能力都有不同的緩存大小。 – Scott 2010-09-28 15:31:00

+0

@Scott,除非你使用Commons Pool的SoftReferenceObjectPool,否則你不會在下面使用軟引用。此外,Commons Pool是一個池化實現,而不是緩存。它有自己的驅逐算法,顯然與GC不同。因此,您可能想要檢查是否有任何驅逐對象 - 沒有任何驅逐將解釋OOME。 – 2010-09-28 15:48:25

+0

如果我們將maxIdle設置爲1,並將whenExhaustedAction設置爲BLOCK,則不應該將其用作緩存嗎?我們正在使用GenericKeyedObjectPool – Scott 2010-09-28 15:54:22