我需要使用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