java.lang.OutOfMemoryError:初始化数组时的java堆空间

java.lang.OutOfMemoryError:初始化数组时的java堆空间,java,arrays,initialization,Java,Arrays,Initialization,我试图初始化一个布尔类型的数组,它的大小是10位整数。它不断抛出OutOfMemoryException。我已经将eclipse的堆空间大小从256增加到1024。有什么我没做的吗 int size = 1000000000; boolean[] primesList = new boolean[size]; 从 此数据类型表示一位信息,但其“大小”并不是精确定义的 如果考虑布尔值至少一个字节,即 1000000000 字节,则需要代码> 953Mb内存。< /P> 因此,这是唯一一个占用10

我试图初始化一个布尔类型的数组,它的大小是10位整数。它不断抛出OutOfMemoryException。我已经将eclipse的堆空间大小从256增加到1024。有什么我没做的吗

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

此数据类型表示一位信息,但其“大小”并不是精确定义的

如果考虑布尔值至少一个字节,即<代码> 1000000000 字节,则需要<数组>代码> 953Mb</代码>内存。< /P> 因此,这是唯一一个占用

1024MB
953MB
的数组,这可能是导致问题的原因


但在一个好的环境中,我想这个用例不需要:)

启动JVM时,需要传递-Xmx参数以将最大堆空间设置为更高

还请注意,数组的最大大小为Integer.MAX_VALUE

Use,与使用
布尔
数组相比,它将位压缩在八分之一的空间中

布尔数组元素使用1字节而不是1位的原因是(大多数)CPU体系结构不提供直接读取和写入单个内存位的能力。个人计算机能操作的最小单位是8位。JVM可以将这些位打包在一起,然后为了修改一个位,它将读取字节,修改字节,然后将其写回,但如果多个线程同时修改数组,则这不起作用

对于原始数组,它是10亿个布尔值,每个布尔值一个字节,即10亿字节或~954 MB。所以1024MB的堆应该足够了(?)。可能它找不到足够大的连续内存块,或者您没有正确设置内存参数。打印
Runtime.getRuntime().maxMemory()
的值,以找出Java正在使用的最大堆大小。对于1024MB,参数应为
-Xmx1024M


最后一点注意:从Java7开始,您可以在数字中使用下划线,以使其更具可读性。因此,您可以编写
1\u 000\u 000
而不是
100000000

您可以使用对象持有者,避免需要一次分配所有空间-如果堆大小足够大,这可能会解决问题。在一个数组中容纳那么多布尔值需要很大的空间——请确保为堆空间设置了最小和最大大小。
也可以使用类似列表的方法,仅在需要时填充值。如果您确实需要将其转换为数组,可以通过多种方式进行转换(apache commons中的数组集合允许您使用Arrays.toPrimitive)。

布尔数组存储为字节:


我认为您需要重新考虑一下您是如何做到这一点的-创建大小为GB的数据结构超出了当前硬件的能力。

只需请求更多堆大小,例如-X1500M肯定可以。您的数组占用100000000字节,但您需要请求更多字节,因为Java堆分为新的+旧的几代。

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

  • 根据这篇文章,JVM不会将整个Xmx量分配给您的程序。其中一个幸存者空间占用的空间会被打折,因为JVM会在内部将其用于一些簿记或临时使用。这可能就是为什么在这种情况下1024 MB是不够的,因为您的阵列已经在使用954 MB。幸存者空间可能超过70 MB。如下文所述,增加Xmx可能有帮助,也可能没有帮助

  • 根据这篇文章,如果您的数据结构对于堆中的任何一代(eden、from/to survivor、old gen)来说都太大,则可以使用OOM。您可以使用-XX:+PrintGCDetails查看每一代的收益。因此,您必须不断增加Xmx,直到其中至少有一个(eden、from/to、old gen)足够大以容纳您的对象,或者您必须显式地设置不同堆区域的大小(例如,-XX:NewSize for Young gen)


  • 你真的需要这么大的空间吗?首先计算:大小*4字节加上其他对象。使用instead@ajozwik你从哪里得到的大小*4字节?请参阅@GarethDavis,它可能用于生成素数筛或用于任意数的素数测试,这需要一个这样的随机访问数组来提高性能。你在那里添加了一个零,布尔值不需要一位,至少在这种形式下。你计算错了。有10位数字,而不是11位。@ViktorOzerov是的,你说得对,多余的零已经被删除了。谢谢你的指点。