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.