Java 8 Arraylist Огромная емкость (int)
Я читаю документацию о том, как ArrayList
в Java выращены. Я не понимаю, почему метод hugeCapacity(int minCapacity)
решает вернуть либо Integer.MAX_VALUE
, либо MAX_ARRAY_SIZE
.
Из того, как MAX_ARRAY_SIZE
определяется в классе,
244 | private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
Это почти то же самое, что и Integer.MAX_VALUE
за исключением размера одного целого (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 | }
Может ли кто-нибудь сказать мне, в чем заключается тонкая разница в возвращении Integer.MAX_VALUE
против MAX_ARRAY_SIZE
? В любом случае, не следует ли OutOfMemoryError
?
Ответы
Ответ 1
Максимальный размер массива ограничен некоторым числом, которое зависит от разных JVM и обычно немного меньше Integer.MAX_VALUE
. Поэтому, выделяя массив элементов Integer.MAX_VALUE
, у вас будет OutOfMemoryError
на большинстве JVM, даже если у вас достаточно памяти для этого. MAX_ARRAY_SIZE
считается допустимым размером массива на большинстве существующих JVM. Поэтому, когда размер ArrayList
приближается к Integer.MAX_VALUE
(например, у вас есть более 1_500_000_000 элементов и нужно увеличить массив), он увеличивается до этого MAX_ARRAY_SIZE
, поэтому его можно успешно выполнить (если у вас достаточно памяти), Только если число элементов превышает MAX_ARRAY_SIZE
, ArrayList
пытается выделить массив элементов Integer.MAX_VALUE
(который, скорее всего, не удастся на большинстве JVM, но может преуспеть в некоторых из них). Таким образом, вы можете безопасно добавлять элементы до MAX_ARRAY_SIZE
практически на любой JVM, и только после этого будут проблемы.
Ответ 2
Из реализации Oracle (обновление 8 для Java 8):
/**
* 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;
Они возвращают (2 31 - 1) - 8 чтобы убедиться, что их код не создает OutOfMemoryError
при выполнении другой реализацией VM.