我需要使用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 the
第bit instead of adding
l to
list1'然後用這個類的對象創建虛擬HashMap,那麼關於內存的結果是不同的。令人驚訝的是,內存在HashMap上的remove
操作之後被回收。例如。在移除HahsMap內存中約80%的條目後,也將約減少40%。
分配給ArrayList的內存沒有被回收嗎? :(:(
當你刪除條目本身被刪除,但散列表仍然分配給它的「峯值」大小,但這應該是幾乎不可估量的 - 大部分空間在obj中這些條目佔用了實際散列表空間的幾倍。你幾乎可以肯定地看到你以某種方式將它們「連在一起」或「一些」之類的「泄漏」的物體。 – 2014-09-01 03:39:13
您需要學習如何使用堆分析器並找出程序的哪部分保留對值對象的引用。 – 2014-09-01 04:32:22
可能是[錯誤java.lang.OutOfMemoryError:超出GC開銷限制]的欺騙(http://stackoverflow.com/questions/1393486/error-java-lang-outofmemoryerror-gc-overhead-limit-exceeded) – markspace 2014-09-01 05:16:15