2014-09-01 58 views
2

我需要使用HashMap的鍵是Long數據類型和值是一些用戶對象,其定義爲:使用爲什麼刪除大量(〜80%)的密鑰後,HashMap的大小沒有變化?

dummy.add(SomeLong,new SomeClass(SomeParameters); 
加入

HashMap <Long,SomeClass> dummy=new HashMap<>(); 

最初,這dummy HashMap中包含了約1000萬<key,value>對,

消耗的內存是7-8GB。創建此映射後,80-90%的條目將被刪除:

for (Iterator<Entry<Long, SomeClass>> it = collisionMap.entrySet().iterator(); it.hasNext();) { 
    Map.Entry<Long,SomeClass> entry = it.next();   
    if(SomeCondition) { 
     it.remove(); 
    } 
} 

刪除這些條目後使用的內存仍然相同。我檢查了Runtime.getRuntime().totalMemory()Runtime.getRuntime().freeMemory()

現在的問題是爲什麼內存在這個remove()操作後未被回收? 我在程序過程中創建了大約1000-2000次這種類型的hashmap。而它給java.lang.OutOfMemoryError: GC overhead limit exceeded錯誤:(

誰能幫助? 感謝

*****************更新/附加信息**** ************

SomeClass被定義爲:

Class SomeClass { 
    private ArrayList <Integer> list1; 
    private ArrayList <Integer> list2;  
    public SomeClass(int l,List <Integer> l2) { 
    list2=l2; 
    list1=new ArrayList<>(); 
    list1.add(l); 
    }  
    public void addList1(int l) { list1.add(l); } 
    public ArrayList <Integer> getList1() { return list1; } 
    public ArrayList <Integer> getList2() { return list2; }  
} 

由於種種原因,我早些時候曾計劃使用BitSet數據類型而不是ArrayList list1。如果我替換list1' by a BitSet variable and set thebit instead of adding l to list1'然後用這個類的對象創建虛擬HashMap,那麼關於內存的結果是不同的。令人驚訝的是,內存在HashMap上的remove操作之後被回收。例如。在移除HahsMap內存中約80%的條目後,也將約減少40%。

分配給ArrayList的內存沒有被回收嗎? :(:(

+2

當你刪除條目本身被刪除,但散列表仍然分配給它的「峯值」大小,但這應該是幾乎不可估量的 - 大部分空間在obj中這些條目佔用了實際散列表空間的幾倍。你幾乎可以肯定地看到你以某種方式將它們「連在一起」或「一些」之類的「泄漏」的物體。 – 2014-09-01 03:39:13

+0

您需要學習如何使用堆分析器並找出程序的哪部分保留對值對象的引用。 – 2014-09-01 04:32:22

+0

可能是[錯誤java.lang.OutOfMemoryError:超出GC開銷限制]的欺騙(http://stackoverflow.com/questions/1393486/error-java-lang-outofmemoryerror-gc-overhead-limit-exceeded) – markspace 2014-09-01 05:16:15

回答

0

java.lang.OutOfMemoryError: GC overhead limit exceeded

這表明你不必使用過多的內存(雖然地圖可能消耗高達80MB爲您的情況的內部節點陣列),但在GC沒有足夠呼吸的空間(最大堆限制)或CPU時間(GC時間限制)可以做的工作給你的分配方案。

你最有可能來調整您的GC參數,以避免此問題。