靜態多層Map緩存清除

最近重構項目遇到一個問題。一個本地緩存的Map凌晨定時清除數據,但好幾天了都沒清除。內存累加,執行500W的數據會增長將近2.86G的內存,雖然暫時服務器還夠用,不過感覺總有一天會掛掉。

啓動時內存佔用:

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                   
81159 root      20   0 28.951g 1.320g  14724 S   0.0  1.1   0:12.76 java   

執行500W數據後的內存佔用:

 PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                   
 81159 root      20   0 33.399g 4.186g  14956 S   0.0  3.3  14:14.34 java 

Map定義如下:

public static Map<Integer, Map<Long, List<Long>>> USER_REPEAT = new ConcurrentHashMap<Integer, Map<Long, List<Long>>>();

百度了一下解決方法,說靜態變量無法被GC,而且如果有地方引用也不會回收。不過new的對象可以被回收。
第一種,調用clear()方法後設置map=null;

USER_REPEAT.clear();
USER_REPEAT=null;

第二種,循環刪除;

for (Map.Entry<Integer, Map<Long, List<Long>>> entry : USER_REPEAT.entrySet()) {
    USER_REPEAT.remove(entry.getKey());
}

測試上面兩張方法後GC,內存無明顯變化。
想了一下是不是可能兩層嵌套的原因。寫了個循環刪除。果然刪除後內存有明顯的變化。

Map<Long, List<Long>> subMap = null;
for (Integer key : USER_REPEAT.keySet()) {
    subMap = USER_REPEAT.get(key);
    for (Long subKey : subMap.keySet()) {
        subMap.remove(subKey);
    }
    USER_REPEAT.remove(key);
}

測試95W簡單數據內存變化
監控堆從163M降到10M

分析了下原因應該是直接刪除key但是沒有刪除子Map中對List的引用,導致內存不釋放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章