Java 8的ArrayList hugeCapacity(int)实现

15

我正在阅读Java中的ArrayList如何增长的文档。我不理解为什么hugeCapacity(int minCapacity)方法选择返回Integer.MAX_VALUEMAX_ARRAY_SIZE

从类中MAX_ARRAY_SIZE的定义方式来看,

244 |     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

Integer.MAX_VALUE几乎相同,只是少了一个整数的大小(32位)。

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_VALUEMAX_ARRAY_SIZE 的微妙差别是什么吗?无论哪种方式,都应该会导致 OutOfMemoryError,对吧?


2
答案就在上面的注释MAX_ARRAY_SIZE中:“要分配的数组的最大大小。一些虚拟机在数组中保留一些头字。尝试分配更大的数组可能会导致OutOfMemoryError:请求的数组大小超过了VM限制。”意思是:如果我们可以避免在某些VM上出现OutOfMemory,我们将这样做,否则,我们将分配Integer.MAX_VALUE,并且如果你很幸运(取决于VM),则会成功。 - Yoav Gur
2个回答

13
最大数组大小在不同的JVM上有所限制,通常略小于Integer.MAX_VALUE。因此,即使你有足够的内存,分配Integer.MAX_VALUE元素的数组,在大多数JVM上都会导致OutOfMemoryError。MAX_ARRAY_SIZE被认为是现有大多数JVM上的有效数组大小。因此,当ArrayList的大小接近Integer.MAX_VALUE时(例如,你有超过1_500_000_000个元素并需要扩大数组),它就会扩展到这个MAX_ARRAY_SIZE,这样就可以成功进行操作(假设你有足够的内存)。只有当元素数量超过MAX_ARRAY_SIZE时,ArrayList才尝试分配一个Integer.MAX_VALUE元素的数组(大多数JVM上可能会失败,但在某些JVM上可能会成功)。通过这种方式,你可以在几乎任何JVM上安全地添加元素,直到达到MAX_ARRAY_SIZE后才会遇到问题。

2

从Oracle的实现(Java 8更新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;

为了确保他们的代码在其他虚拟机实现中执行时不会出现OutOfMemoryError,他们返回(2 31 - 1) - 8


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接