附 Java物件記憶體佈局
注意:本篇部落格,主要參考自《深入理解Java虛擬機器(第二版)》
1、物件在記憶體中儲存的佈局分為三塊
- 物件頭
- 儲存物件自身的執行時資料:Mark Word(在32bit和64bit虛擬機器上長度分別為32bit和64bit),包含如下資訊:
- 物件hashCode
- 物件GC分代年齡
- 鎖狀態標誌(輕量級鎖、重量級鎖)
- 執行緒持有的鎖(輕量級鎖、重量級鎖)
- 偏向鎖相關:偏向鎖、自旋鎖、輕量級鎖以及其他的一些鎖優化策略是JDK1.6加入的,這些優化使得Synchronized的效能與ReentrantLock的效能持平,在Synchronized可以滿足要求的情況下,優先使用Synchronized
- 型別指標:物件指向類元資料的指標(32bit-->32bit,64bit-->64bit(未開啟壓縮指標),32bit(開啟壓縮指標))
-
JVM通過這個指標來確定這個物件是哪個類的例項(根據物件確定其Class的指標)
-
- 例項資料:物件真正儲存的有效資訊
- 對齊填充
- JVM要求物件的大小必須是8的整數倍,若不是,需要補位對齊
2、注意
- Mark Word具有非固定的資料結構,以便在極小的空間記憶體儲儘量多的資訊
- 如果物件是一個數組,物件頭必須有一塊兒用於記錄陣列長度的資料。JVM可以通過Java物件的元資料確定物件長度,但是對於陣列不行。
- 對於物件頭長度而言
- 32bit虛擬機器一定是32bit+32bit,即8位元組
- 64bit虛擬機器若沒有開啟了壓縮指標,是64bit+64bit,即16位元組,若開啟了壓縮指標,是64bit+32bit,即12位元組(不是8bit的倍數)
- -XX:+UseCompressedOops:開啟壓縮指標
- 在《深入理解Java虛擬機器(第二版)》中,說物件頭是8位元組或16位元組,不知道是不是有誤,自己的系統不是64bit,沒有測試
- 基本資料型別與對應包裝類的選用
在實際使用中,我們會根據位元組數較小的一方來選用基本資料型別還是使用其包裝類。