Java堆空间溢出:初始化数组时发生java.lang.OutOfMemoryError异常。

8

我正在尝试初始化一个布尔类型的数组,其大小为10位数字。它一直抛出OutOfMemoryException。我已将Eclipse的堆空间大小从256增加到1024。我是否还有遗漏需要补充?

int size = 1000000000;
boolean[] primesList = new boolean[size];

4
你真的需要那么大的空间吗? - RaceBase
请参见https://dev59.com/F3RC5IYBdhLWcg3wMd9S。 - Andrzej Jozwik
这个数组大概需要1g的空间。不要吝啬,给堆4g的空间。 - Ingo
请参见规范:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.3.4 - Andrzej Jozwik
1
@GarethDavis 这可能是为了生成素数筛或对任意数字进行素性测试,这需要像这样的随机访问数组以获得更好的性能。 - Boann
显示剩余3条评论
7个回答

13
使用java.util.BitSet,相较于使用boolean数组,它会将位压缩到八分之一的空间中。
布尔数组元素占用1字节而非1位的原因是,(大多数)CPU架构不提供直接读写内存单独的位的能力。PC可以操作的最小单位为8位。Jvm可以将位打包在一起,然后修改位时会读取字节、修改它,再写回去,但如果多个线程同时修改数组,则会出现问题。
至于您最初的数组,它是10亿个布尔值,每个值占用1字节,即10亿字节或~954 MB。因此,1024 MB堆应该足够了(?)。也许它无法找到足够大的连续内存块,或者您没有正确设置内存参数。打印Runtime.getRuntime().maxMemory()的值以找出Java正在使用的最大堆大小。对于1024 MB,参数应为-Xmx1024M
最后注意:自Java 7以来,您可以在数字中使用下划线来使它们更可读。因此,您可以编写1_000_000_000而不是1000000000

3

来自文档

这种数据类型代表一位信息,但它的“大小”并没有被精确地定义。

如果您考虑布尔值至少需要一个字节,那么使用1000000000个字节的数组需要953MB的内存。

因此,这是唯一占用了1024MB953MB的数组,这可能导致问题。

但在一个好的世界里,我想这种情况不会发生 :)


你在那里加了一个零,而且布尔值不只占用一位,至少在这种形式下不是。 - Kayaman
你计算错误了。这是一个10位数,而不是11位数。 - Viktor Ozerov
@ViktorOzerov 是的,你说得对,多余的零已经被删除了。感谢你指出。 - Suresh Atta

1

只需请求更多的堆大小,例如-X1500M绝对有效。你的数组占用了1000000000字节,但是你需要请求更多的空间,因为Java堆被分成新生代和老年代。


0
在启动JVM时,需要传递“-Xmx”参数以将最大堆空间设置得更高。
此外,请注意数组的最大大小为Integer.MAX_VALUE。

0
你可以使用对象容器来避免一次性分配所有空间的需要,这可能会解决堆大小足够大的问题。你需要很多空间来存储那么多布尔值的数组- 确保堆空间的最小和最大大小已设置。 也可以使用类似 List 的东西,在需要时只填充值。如果你真的需要它作为一个数组,有办法转换回来(apache commons 中的 Arrays collection 可以让你使用 Arrays.toPrimitive)。

0

布尔数组以字节形式存储:

https://forums.oracle.com/thread/2550321

我认为你需要重新考虑你正在做的事情 - 创建大小在几千兆字节以上的数据结构已经超出了当前硬件的能力范围。


0

这可能是由于以下两个原因之一:

根据this文章,JVM不会将整个Xmx分配给您的程序。其中一个survivor空间占用的空间被折扣,因为JVM在内部使用它进行一些簿记或临时使用。这可能是为什么在这种情况下1024 MB不足够,因为您的数组已经使用了954 MB。survivor空间可能超过70 MB。增加Xmx可能有助于解决问题,也可能无法解决问题,如下面所述。
根据this文章,如果您的数据结构对堆中的任何一代(eden、from/to survivor、old gen)来说太大,就会出现OOM。您可以使用-XX:+PrintGCDetails查看每个代收到的数量。因此,您必须不断增加Xmx,直到其中至少一个代(eden、from/to、old gen)足够大以容纳您的对象,否则您将不得不显式设置不同堆区域的大小(例如,-XX:NewSize用于Young gen)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接