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?
int size = 1000000000;
boolean[] primesList = new boolean[size];
From docs
If you consider at least one byte for boolean, that
1000000000
byte , requires953MB
memory for your array.So that is the only array eating up
953MB
of1024MB
, might that causing the problem.But in a good world this use case won't require I guess :)
It could be very well due to the following two reasons:
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
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).
Use java.util.BitSet, which will pack the bits in one-eighth of the space compared to using a
boolean
array.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.
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
.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 of1000000000
.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).
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.
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.