java.lang.OutOfMemoryError:Java堆空间异常

时间:2018-06-26 09:26:10

标签: java

在运行以下代码段时,我遇到了"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堆大小足够容纳数组。

3 个答案:

答案 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()来更改其大小,因此需要更多内存来调整列表本身的大小,以确保在填充时其容量足够。