问题
I'm reading the documentation for how ArrayList
s in Java are grown. I don't understand why the hugeCapacity(int minCapacity) method chooses to return either Integer.MAX_VALUE
or MAX_ARRAY_SIZE
.
From how MAX_ARRAY_SIZE
is defined in the class,
244 | private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
It's almost the same as Integer.MAX_VALUE
except off by the size of one integer (32 bits
).
264 | private static int hugeCapacity(int minCapacity) {
265 | if (minCapacity < 0) // overflow
266 | throw new OutOfMemoryError();
267 | return (minCapacity > MAX_ARRAY_SIZE) ?
268 | Integer.MAX_VALUE :
269 | MAX_ARRAY_SIZE;
270 | }
Can anyone tell me what the subtle difference is in returning Integer.MAX_VALUE
versus MAX_ARRAY_SIZE
? Either way, shouldn't an OutOfMemoryError
occur?
回答1:
The maximal array size is limited to some number which varies across different JVMs and usually is slightly less than Integer.MAX_VALUE
. So allocating the array of Integer.MAX_VALUE
elements you will have OutOfMemoryError
on most of JVMs even if you have enough memory to do it. MAX_ARRAY_SIZE
assumes to be valid array size on the most of existing JVMs. So when ArrayList
size approaches to Integer.MAX_VALUE
(for example, you have more than 1_500_000_000 elements and need to enlarge an array), it's enlarged to this MAX_ARRAY_SIZE
, so it can be successfully performed (assuming you have enough memory). Only if number of elements exceeds MAX_ARRAY_SIZE
, the ArrayList
tries to allocate an array of Integer.MAX_VALUE
elements (which will likely to fail on most of JVMs, but may succeed on some of them). This way you can safely add elements up to MAX_ARRAY_SIZE
on almost any JVM and only after that will have problems.
回答2:
From Oracle's implementation (Java 8 update 31):
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
They return (2 31 - 1) - 8 to make sure their code do not create OutOfMemoryError
when executed by another VM implementation.
来源:https://stackoverflow.com/questions/35582809/java-8-arraylist-hugecapacityint-implementation