1、對象頭(Header)
- 對象自身運行時數據(mark word):hash 碼、GC 分代年齡、鎖狀態標識、是否偏向鎖、線程持有的鎖、偏向線程ID、偏向時間戳;
- 類型指針:對象指向元數據的指針。
mark word:
對象頭信息與對象自身定義的數據無關的額外存儲成本,考慮到虛擬機的空間效率,對象頭信息被設計成一個非固定的數據結構以便在極小的空間內存儲盡量多的信息 ,它對根據對象的狀態復用自己的存儲空間。
下圖描述 32位虛擬機 上,對象不同狀態時 mark word 比特位區間的含義:
鎖狀態 | 25bit | 4bit | 1bit | 2bit | |
23bit | 2bit | 是否偏向 | 鎖標志位 | ||
無鎖態 | 對象的hashCode | 分代年齡 | 0 | 01 | |
輕量級鎖 | 指向棧中鎖記錄的指針 | 00 | |||
重量級鎖 | 指向互斥量(重量級鎖)的指針 | 10 | |||
GC標記 | 空 | 11 | |||
偏向鎖 | 線程ID | Epoch | 分代年齡 | 1 | 01 |
查找對象元數據的兩種方式:
- 句柄方式:堆中維護一個句柄池,句柄包含類型數據指針和對象數據指針(棧中的 reference 指向句柄池中的句柄,句柄指向堆中的實例,句柄指向方法區的類型數據);
- 直接指針:堆中的對象直接包含類型數據指針(棧中的 reference 指向堆中對象,對象指向方法區中的類型數據 )。
查找元數據兩種方式的區別:
- 句柄方式:棧中的 reference 穩定,需要另外開辟一塊區域(堆中的句柄池),對象移動時,需要修改句柄中實例數據的地址;
- 直接指針:節省一次指針定位開銷,速度更快。
2、實例數據(Instance Data)
各種類型的字段內容(父類 + 子類)。
3、對齊填充(Padding)
占位符(沒有其他作用),虛擬機內存管理系統要求對象起始位置必須是 8 的整數倍,實例數據部分沒有對齊,則填充。
補充:
文中的插圖,可以衍生出很多面試題,如:
1、GC 分代年齡為什么默認為 15?
2、對象鎖狀態類型有幾種?
3、為什么要多 1bit 來標記是否偏向?
......