我刚刚在我们的生产环境中经历了一次相当不愉快的经历,导致OutOfMemoryErrors: heapspace..
我将问题追溯到我的使用ArrayList::new
在一个函数中。
验证这实际上比通过声明的构造函数正常创建执行得更差(t -> new ArrayList<>()
),我写了下面的小方法:
public class TestMain {
public static void main(String[] args) {
boolean newMethod = false;
Map<Integer,List<Integer>> map = new HashMap<>();
int index = 0;
while(true){
if (newMethod) {
map.computeIfAbsent(index, ArrayList::new).add(index);
} else {
map.computeIfAbsent(index, i->new ArrayList<>()).add(index);
}
if (index++ % 100 == 0) {
System.out.println("Reached index "+index);
}
}
}
}
运行该方法newMethod=true;
将导致该方法失败OutOfMemoryError
就在指数触及30k之后。和newMethod=false;
该程序不会失败,但会继续运行,直到被杀死(索引很容易达到 150 万)。
为什么ArrayList::new
创造这么多Object[]
它导致的堆上的元素OutOfMemoryError
很快?
(顺便说一句 - 当集合类型为HashSet
.)
在第一种情况下(ArrayList::new
)您正在使用构造函数 https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#ArrayList-int-它需要一个初始容量参数,在第二种情况下则不需要。初始容量大(index
在你的代码中)会导致很大的Object[]
被分配,导致你的OutOfMemoryError
s.
以下是两个构造函数的当前实现:
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
类似的事情发生在HashSet
,除非数组直到add
叫做。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)