附 Java對象記憶體布局,java物件版面配置
注意:本篇部落格,主要參考自《深入理解Java虛擬機器(第二版)》
1、對象在記憶體中儲存的布局分為三塊
- 對象頭
- 儲存物件自身的運行時資料:Mark Word(在32bit和64bit虛擬機器上長度分別為32bit和64bit),包含如下資訊:
- 對象hashCode
- 對象GC分代年齡
- 鎖狀態標誌(輕量級鎖、重量級鎖)
- 線程持有的鎖(輕量級鎖、重量級鎖)
- 偏向鎖相關:偏向鎖、自旋鎖、輕量級鎖以及其他的一些鎖最佳化策略是JDK1.6加入的,這些最佳化使得Synchronized的效能與ReentrantLock的效能持平,在Synchronized可以滿足要求的情況下,優先使用Synchronized,除非是使用一些ReentrantLock專屬的功能,例如指定時間等待等。
- 類型指標:對象指向類別中繼資料的指標(32bit-->32bit,64bit-->64bit(未開啟壓縮指標),32bit(開啟壓縮指標))
- 執行個體資料:對象真正儲存的有效資訊
- 對齊填充
- 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,沒有測試
- 基礎資料型別 (Elementary Data Type)與對應封裝類的選用
在實際使用中,我們會根據位元組數較小的一方來選用基礎資料型別 (Elementary Data Type)還是使用其封裝類。
- 在《第二章 JVM記憶體配置 》中說過,實際對象所佔的記憶體大小在類載入完成後就可以知道了,具體是怎樣計算的,可以參看這一篇文章http://www.importnew.com/14948.html