Java代码如下:
Random r = new Random(1234697890);
HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<100000;i++){
for(int j=0;j<1000;j++){
list.add(r.nextInt(100000));
}
map.put(i, list);
map.remove(i);
}
当i
达到37553时,java.lang.OutOfMemoryError: Java heap space
发生
垃圾收集似乎不会在循环中发生
现在我想知道如何解决这个问题。
答案 0 :(得分:5)
您始终使用相同的List,循环退出时包含100000 * 1000个项目。要使GC能够删除列表,您需要将其范围缩小到for(i)
循环内。
换句话说,地图和列表都可以在该段代码中随时访问,因此不符合收集条件。
答案 1 :(得分:5)
尝试按如下方式重写代码,你不应该得到OOME的......
Random r = new Random(1234697890);
HashMap<Integer, List<Integer>> map = new HashMap<Integer, List<Integer>>();
for(int i=0;i<100000;i++){
List<Integer> list = new ArrayList<Integer>();
for(int j=0;j<1000;j++){
list.add(r.nextInt(100000));
}
map.put(i, list);
map.remove(i);
}
原始代码的问题在于:
在循环中移动list
声明意味着在每次循环迭代中创建并填充新的ArrayList
,并在开始下一次迭代时变为垃圾。
有人建议拨打System.gc()
。在你的情况下它根本没有帮助,因为要收集最少的 1 垃圾。总的来说,这是一个坏主意,因为:
System.gc()
的通话可能完全被忽略。可以配置JVM以忽略对System.gc()
的调用。 1 - 我的学究者想指出map.put(i, list); map.remove(i);
最有可能生成一个很可能变成垃圾的Integer
对象。但是,与您无限增长的ArrayList
对象相比,这是“鸡饲料”。 子>
答案 2 :(得分:0)
在你的情况下,你继续填充相同的list
(即使你从那个HashMap中删除它,它仍然作为局部变量存在)。
JVM承诺在抛出OutOfMemoryError
之前进行完整的垃圾收集。所以你可以肯定没有什么可以清理的。
答案 3 :(得分:0)
您的代码
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<100000;i++){
for(int j=0;j<1000;j++){
list.add(r.nextInt(100000));
}
map.put(i, list);
map.remove(i);
}
与
相同List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<100000 * 1000; i++) {
list.add(r.nextInt(100000));
}
正如你可以看到它的List,而不是保留所有整数的地图。顺便试试这个,看看会发生什么;)
list.add(r.nextInt(128));