在运行以下代码段时,我遇到了"java.lang.OutOfMemoryError: Java heap space"
异常。我已使用命令8192M
设置了JVM堆大小set JVM_ARGS="-Xms8192m -Xmx8192m"
。
List<Integer> largeList = new ArrayList<>();
Random rand = new Random();
for(int i=0;i<Integer.MAX_VALUE/2;i++)
{
largeList.add(rand.nextInt(Integer.MAX_VALUE));
}
我认为我设置的JVM堆大小足够容纳数组。
答案 0 :(得分:8)
List
只能容纳对象。
Integer
对象的实际值至少需要4个字节,而与各种对象相关的开销则需要一定数量的字节(因JVM而异,但每个对象通常约为16-30字节)。
Integer.MAX_VALUE / 2
大约十亿。因此,仅对于数据(没有对象开销),您就需要40亿字节来存储列表。那是4GB。因此,即使对象开销只有4个字节(很难做到,并且在运行时可能效率不高),这也已经耗尽了整个8GB的堆空间(并且对于运行代码所需的所有类都一无所有) 。而且,这甚至不包括为ArrayList
保留的内存,该内存需要保留许多引用(为8字节或4字节,具体取决于所用的JVM和使用的设置)。
因此,您没有为其分配足够的内存。
如果您实际上需要那么多的int
值,请考虑使用int[]
,它的内存效率明显高于此值,每int
有效地占用4个字节固定费用很小。
答案 1 :(得分:4)
当ArrayList满时,其大小将增加50%-因此列表的大小可能高达0.75 * MAX_VALUE = 0.75 * 2 ^ 31 = 16亿。
一个Integer在内存中占用16个字节,并且每个Integer引用在列表中占用4或8个字节。让我们在这里假设4。因此,您的列表最多可能需要10亿* 16 + 6亿* 4(对于空条目)= 30 GB内存。
答案 2 :(得分:0)
int
的大小为4个字节,因此从理论上讲,由于包装程序的开销,堆中将有超过4 GB的Integer
;另一点是ArrayList
通过使用Arrays.copyOf()
来更改其大小,因此需要更多内存来调整列表本身的大小,以确保在填充时其容量足够。