網站首頁 編程語言 正文
/**
* 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;
看過 Arraylist 代碼的小伙伴是不是看到這個總會有疑惑:
- 為什么 MAX_ARRAY_SIZE 是等于 Integer.MAX_VALUE - 8,為啥不是-16或者其他數字。
我看了很多回答,他們總是把這個 十進制的8 和 java的對象頭聯系在一起說,我到現在都不能理解這兩個怎么畫等號的。
思索了很久,再結合源碼的注釋,我開始想是不是兄弟們把這個問題想復雜了啊。
注釋清清楚楚寫著:Some VMs(一些VM)在數組中會有保留字,嘗試分配更大的數組可能會導致OutOfMemoryError。
所以這個 Integer.MAX_VALUE - 8 其實是為了保證這些(Some VMs)減少報錯的幾率(?)
這里我們打個問號,下面我們分析分析。
這個變量只在 grow() 和 hugeCapacity() 兩個方法里面用到了。
先看看 grow() 方法:
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
里面第二個if里面會判斷 newCapacity 是否大于了 MAX_ARRAY_SIZE,大于了就調用 hugeCapacity() 方法。
再看看 hugeCapacity() 方法:
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
為什么第一個if判斷 minCapacity 小于 0 就是代表溢出,minCapacity 什么時候會溢出了,就是當我們的數組已經達到 Integer 的最大值 2^31-1 的時候,他增加一個元素后, 即 minCapacity 等于 2^31 時,這個數從二進制變成十進制就是個負數,所以直接判斷 minCapacity 是否小于 0 就能判斷是否溢出了。
我再強調一下幾個變量的意義:
- newCapacity :預計擴容后的數組長度。
- minCapacity : 原數組增加元素后需要的數組長度。
- MAX_ARRAY_SIZE : Integer.MAX_VALUE - 8
看到return里面的三元表達式,再結合 grow() 方法里面的第二個if判斷,思路是不是清晰起來了。
- 首先 預計擴容后的數組長度(newCapacity) 大于了 MAX_ARRAY_SIZE。
- 再判斷 原數組增加元素后需要的數組長度(minCapacity ) 是不是大于 MAX_ARRAY_SIZE。
- 如果大于了 MAX_ARRAY_SIZE,那還是會將 預計擴容后的數組長度(newCapacity) 置為 Integer.MAX_VALUE。
- 如果不大于 MAX_ARRAY_SIZE ,則將 預計擴容后的數組長度(newCapacity) 置為 MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)。
你會發現他依舊可能會擴容到 Integer.MAX_VALUE,所以我們可以得知:
Arraylist 的最大容量依舊是 Integer.MAX_VALUE ,而不是 Integer.MAX_VALUE - 8。
很多人看到 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 這句代碼,就說 Arraylist 的最大容量是 Integer.MAX_VALUE - 8 ,這是不對的。
到這里可能還會有人會接著問,那最后都是會到 Integer.MAX_VALUE ,那用一個 MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8) 做判斷有啥意義。
所以我這里就有了文章開始的那些猜測,這個 MAX_ARRAY_SIZE 值只是為了保證這些(Some VMs)減少報錯的幾率的。
如果沒有這個 MAX_ARRAY_SIZE 的話,這些(Some VMs)在 數組長度為 Integer.MAX_VALUE 的 2/3 左右的時候,一旦觸發擴容,newCapacity 直接大于 Integer.MAX_VALUE - 8,然后報錯 。
如果有了 MAX_ARRAY_SIZE 的話,那么這些(Some VMs)會在 數組長度為 Integer.MAX_VALUE - 8 的時候,再增加元素才會報錯,其他VM會正常的擴容到 nteger.MAX_VALUE。
這樣極大的減少了這些(Some VMs)的報錯幾率。并且為這些(Some VMs)增加了接近1/3的實際儲存容量。
最后說明,以上絕大部分都是我的推理,我至此也沒查到為啥一定是 8 這個數字,我只能想到這個十進制的8代表二進制數組的最后四位為0,除此之外我并不曉得在這里的具體含義。
望大家一起探討探討。
原文鏈接:https://blog.csdn.net/z55947810/article/details/127249701
相關推薦
- 2022-07-19 CentOS8 服務器連接超時自動斷開問題解決
- 2022-11-05 利用Go語言實現輕量級OpenLdap弱密碼檢測工具_Golang
- 2022-11-17 Android使用元數據實現配置信息的傳遞方法詳細介紹_Android
- 2022-05-06 C語言結構體使用之鏈表_C 語言
- 2022-10-16 Python?讀取?Word?文檔操作_python
- 2022-04-16 C++中allocator類使用示例_C 語言
- 2023-02-23 Python實現隨機生成一個漢字的方法分享_python
- 2022-06-07 Pytorch上下采樣函數之F.interpolate數組采樣操作詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支