关于为何要减8这个问题,可以从出现何种错误的角度去看。
你可以在程序中试图直接分配Integer.MAX_VALUE大小的ArrayList。
ArrayList<Integer> list = new ArrayList<>(Integer.MAX_VALUE);
此时,你大概率得到一个错误:
Requested array size exceeds VM limit
译文:请求的数组大小超过 VM 限制
其实这就是为什么会有减8出现的原因。
由于在不同的平台上,受到平台的影响导致能够为数组分配的实际最大数值并非为Integer.MAX_VALUE(2,147,483,647),而是与这个值相接近的数值。
因此,作者减8实际上是因为不想让你创建的数组在扩容时计算的新容量值等于或过于接近最大值不能被平台分配出来而报出上述错误。
这样你的程序在不同平台上运行时不会因为分配数值过大而被平台限制而出现报错。换言之,Integer.MAX_VALUE-8
将会保证你的程序在任何平台上都不会因为分配问题而报出Requested array size exceeds VM limit
错误。
更多请参考以下网站:
Java 8 Arraylist hugeCapacity(int) implementation - Stack Overflow
接下来,有关于作者在源码中的注释
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
译文:
要分配的数组的最大大小(除非必要)。
有些虚拟机在数组中保留一些头词。
尝试分配更大的数组可能导致
OutOfMemoryError:请求的数组大小超过虚拟机限制
*/
关键在于Some VMs reserve some header words in an array.
这句解释,个人理解这句话想要表示的是有的VM因保存数组对象头而导致不允许分配数组大小达到Integer.MAX_VALUE(至于为何会产生这种限制本人也不太清楚,后续得知将会补充)。所以减8不是表示减去数组对象头8bytes
,而是用于规避不同VM间差异而导致的OutOfMemoryError
错误。只是作者减去的数值正好与数组对象头的数值相同而导致被误解。
欢迎在评论区发表自己的看法!
END