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

时间:2021-06-19 21:30:08

I am trying to initialise an array of boolean type whose size is a 10 digit integer. It keeps on throwing OutOfMemoryException. I have increased the size of the heap space of eclipse to 1024 from 256. Is there anything that I am missing to do?

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

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

7 个解决方案

#1


12  

Use java.util.BitSet, which will pack the bits in one-eighth of the space compared to using a boolean array.

使用java.util.BitSet,与使用布尔数组相比,它将打包空间的八分之一。

The reason boolean array elements take 1 byte instead of 1 bit is because (most) CPU architectures don't provide the ability to directly read and write individual bits of memory. The smallest unit PCs can manipulate has 8 bits. The JVM could pack the bits together, then to modify a bit it would read the byte, modify it, and write it back, but that does not work if multiple threads are modifying the array simultaneously.

布尔数组元素占用1个字节而不是1个比特的原因是因为(大多数)CPU架构不能提供直接读写单个内存位的能力。最小的单元PC可以操作8位。 JVM可以将这些位打包在一起,然后修改它将读取字节的位,修改它并将其写回,但如果多个线程同时修改数组,那么这不起作用。

As to your original array, it's 1 billion booleans, one byte each, which is 1 billion bytes or ~954 MB. So a 1024 MB heap ought to be enough (?). Perhaps it can't find a contiguous chunk of memory big enough, or perhaps you have not set the memory parameter correctly. Print the value of Runtime.getRuntime().maxMemory() to find out the maximum heap size that Java is using. For 1024 MB the parameter should be -Xmx1024M.

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

Final note: As of Java 7 you can use underscores in numbers to make them more readable. So you can write 1_000_000_000 instead of 1000000000.

最后注意事项:从Java 7开始,您可以在数字中使用下划线,以使它们更具可读性。所以你可以写1_000_000_000而不是1000000000。

#2


2  

From docs

This data type represents one bit of information, but its "size" isn't something that's precisely defined.

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

If you consider at least one byte for boolean, that 1000000000 byte , requires 953MB memory for your array.

如果你考虑至少一个字节用于布尔值,那个1000000000字节,你的阵列需要953MB内存。

So that is the only array eating up 953MB of 1024MB, might that causing the problem.

因此,这是唯一一个占用953MB 1024MB的阵列,可能导致问题。

But in a good world this use case won't require I guess :)

但在一个美好的世界中,这个用例不需要我猜:)

#3


1  

Simply request more heap size, eg -X1500M definitely works. Your array occupies 1000000000 bytes, but you need to request more because Java heap is devided into new + old generations.

只需要更多堆大小,例如-X1500M绝对有效。您的阵列占用了1000000000字节,但您需要更多请求,因为Java堆分为新的+旧代。

#4


0  

When starting the JVM you need to pass a -Xmx parameter to set the maximum heap space as higher.

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

Also note that arrays have a maximum size of Integer.MAX_VALUE

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

#5


0  

You could use an object holder instead, avoiding the need to allocate all the space at once- which may get around the problem if the heap size is large enough. You need a lot of space to hold that many booleans in an array- make sure the min and max size are set for the heap space. Use something like List to only fill up values when needed too. If you really need it as an array there are ways to convert back (Arrays collection in apache commons lets you use Arrays.toPrimitive).

您可以使用对象持有者,避免一次性分配所有空间 - 如果堆大小足够大,可能会解决问题。你需要很大的空间来容纳阵列中的许多布尔值 - 确保为堆空间设置最小和最大大小。使用像List这样的东西只在需要时填充值。如果你真的需要它作为一个数组有转换回的方法(在apache commons中的Arrays集合允许你使用Arrays.toPrimitive)。

#6


0  

Boolean arrays are stored as bytes:

布尔数组存储为字节:

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

I think you need to rethink how you are doing this - creating data structures with sizes in the order of gigabytes is beyond the capabilities of current hardware.

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

#7


0  

It could be very well due to the following two reasons:

由于以下两个原因,它可能非常好:

  1. According to this article, JVM does not allocate the entire Xmx amount to your program. The space taken up by one of the survivor spaces is discounted as JVM uses it internally for some bookkeeping or temporary usage. That could be the reason why 1024 MB is not sufficient in this case as your array is already using 954 MB. The survivor space could be over 70 MB. Increasing the Xmx may or may not help as explained in the below point

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

  2. According to this article, you can have OOM if your data structure is too big for any of the generations in the heap (eden, from/to survivor, old gen). You can use -XX:+PrintGCDetails and see how much each of the generations are getting. So, you have to keep increasing your Xmx until at least one of them (eden, from/to, old gen) is big enough to hold your object or you would have to explicitly set the size of the different heap areas (e.g., -XX:NewSize for Young gen).

    根据这篇文章,如果您的数据结构对于堆中的任何一代(eden,from / to survivor,old gen)而言太大,则可以使用OOM。您可以使用-XX:+ PrintGCDetails并查看每代人获得的数量。所以,你必须不断增加你的Xmx,直到它们中的至少一个(eden,from / to,old gen)大到足以容纳你的对象,否则你必须明确设置不同堆区域的大小(例如, - XX:年轻人的NewSize)。

#1


12  

Use java.util.BitSet, which will pack the bits in one-eighth of the space compared to using a boolean array.

使用java.util.BitSet,与使用布尔数组相比,它将打包空间的八分之一。

The reason boolean array elements take 1 byte instead of 1 bit is because (most) CPU architectures don't provide the ability to directly read and write individual bits of memory. The smallest unit PCs can manipulate has 8 bits. The JVM could pack the bits together, then to modify a bit it would read the byte, modify it, and write it back, but that does not work if multiple threads are modifying the array simultaneously.

布尔数组元素占用1个字节而不是1个比特的原因是因为(大多数)CPU架构不能提供直接读写单个内存位的能力。最小的单元PC可以操作8位。 JVM可以将这些位打包在一起,然后修改它将读取字节的位,修改它并将其写回,但如果多个线程同时修改数组,那么这不起作用。

As to your original array, it's 1 billion booleans, one byte each, which is 1 billion bytes or ~954 MB. So a 1024 MB heap ought to be enough (?). Perhaps it can't find a contiguous chunk of memory big enough, or perhaps you have not set the memory parameter correctly. Print the value of Runtime.getRuntime().maxMemory() to find out the maximum heap size that Java is using. For 1024 MB the parameter should be -Xmx1024M.

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

Final note: As of Java 7 you can use underscores in numbers to make them more readable. So you can write 1_000_000_000 instead of 1000000000.

最后注意事项:从Java 7开始,您可以在数字中使用下划线,以使它们更具可读性。所以你可以写1_000_000_000而不是1000000000。

#2


2  

From docs

This data type represents one bit of information, but its "size" isn't something that's precisely defined.

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

If you consider at least one byte for boolean, that 1000000000 byte , requires 953MB memory for your array.

如果你考虑至少一个字节用于布尔值,那个1000000000字节,你的阵列需要953MB内存。

So that is the only array eating up 953MB of 1024MB, might that causing the problem.

因此,这是唯一一个占用953MB 1024MB的阵列,可能导致问题。

But in a good world this use case won't require I guess :)

但在一个美好的世界中,这个用例不需要我猜:)

#3


1  

Simply request more heap size, eg -X1500M definitely works. Your array occupies 1000000000 bytes, but you need to request more because Java heap is devided into new + old generations.

只需要更多堆大小,例如-X1500M绝对有效。您的阵列占用了1000000000字节,但您需要更多请求,因为Java堆分为新的+旧代。

#4


0  

When starting the JVM you need to pass a -Xmx parameter to set the maximum heap space as higher.

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

Also note that arrays have a maximum size of Integer.MAX_VALUE

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

#5


0  

You could use an object holder instead, avoiding the need to allocate all the space at once- which may get around the problem if the heap size is large enough. You need a lot of space to hold that many booleans in an array- make sure the min and max size are set for the heap space. Use something like List to only fill up values when needed too. If you really need it as an array there are ways to convert back (Arrays collection in apache commons lets you use Arrays.toPrimitive).

您可以使用对象持有者,避免一次性分配所有空间 - 如果堆大小足够大,可能会解决问题。你需要很大的空间来容纳阵列中的许多布尔值 - 确保为堆空间设置最小和最大大小。使用像List这样的东西只在需要时填充值。如果你真的需要它作为一个数组有转换回的方法(在apache commons中的Arrays集合允许你使用Arrays.toPrimitive)。

#6


0  

Boolean arrays are stored as bytes:

布尔数组存储为字节:

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

I think you need to rethink how you are doing this - creating data structures with sizes in the order of gigabytes is beyond the capabilities of current hardware.

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

#7


0  

It could be very well due to the following two reasons:

由于以下两个原因,它可能非常好:

  1. According to this article, JVM does not allocate the entire Xmx amount to your program. The space taken up by one of the survivor spaces is discounted as JVM uses it internally for some bookkeeping or temporary usage. That could be the reason why 1024 MB is not sufficient in this case as your array is already using 954 MB. The survivor space could be over 70 MB. Increasing the Xmx may or may not help as explained in the below point

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

  2. According to this article, you can have OOM if your data structure is too big for any of the generations in the heap (eden, from/to survivor, old gen). You can use -XX:+PrintGCDetails and see how much each of the generations are getting. So, you have to keep increasing your Xmx until at least one of them (eden, from/to, old gen) is big enough to hold your object or you would have to explicitly set the size of the different heap areas (e.g., -XX:NewSize for Young gen).

    根据这篇文章,如果您的数据结构对于堆中的任何一代(eden,from / to survivor,old gen)而言太大,则可以使用OOM。您可以使用-XX:+ PrintGCDetails并查看每代人获得的数量。所以,你必须不断增加你的Xmx,直到它们中的至少一个(eden,from / to,old gen)大到足以容纳你的对象,否则你必须明确设置不同堆区域的大小(例如, - XX:年轻人的NewSize)。