深入理解Java虛擬機器之物件的記憶體佈局、訪問定位

JAVA線上發表於2018-09-27

記憶體佈局

在HotSpot虛擬機器中,物件在記憶體中儲存的佈局可以分為三塊區域:物件頭(Header)、例項資料(Instance Data)、對齊填充(Padding)。

物件頭

物件頭分為兩個部分,第一部分儲存自身的執行時資料,如物件的雜湊碼、GC分代年齡、鎖標誌位等。這部分資料的長度在32位和64位的虛擬機器中分別為32bit和64bit,官方稱它為“Mark World”,Mark Word被設計為一個非固定的資料結構,以便在極小的記憶體空間記憶體儲儘量多的資訊,它會根據物件的狀態複用自己的儲存空間。32位HotSpot虛擬機器物件頭Mark Word儲存內容如下:

深入理解Java虛擬機器之物件的記憶體佈局、訪問定位

第二部分是型別指標,即物件指向它的類後設資料的指標,虛擬機器通過這個指標來確定這個物件是哪個類的例項。

如果物件是一個Java陣列,物件頭中還必須有一塊用於記錄陣列長度的資料,因為虛擬機器可以通過普通Java物件的後設資料資訊確定Java物件的大小,但從陣列的後設資料卻無法確定陣列的大小。

例項資料

例項資料部分是物件真正儲存的有效資訊,也是程式程式碼中所定義的各種型別的欄位內容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄下來。這部分的儲存順序會受到虛擬機器分配策略引數(FieldsAllocationStyle)和Java欄位在Java原始碼中定義的順序的影響。HotSpot虛擬機器預設的分配策略為longs/doubles、ints、shorts/chars、bytes/boolean、oops(ordinary object pointers),相同寬度的欄位總是被分配到一起。

對齊填充

對齊填充並不是必然存在的,僅起著佔位符的作用。由於HotSpot VM的自動記憶體管理系統要求物件的起始地址必須是8位元組的整倍數,而物件頭剛好是8位元組的整倍數,所以當物件例項資料部分沒有對齊時,就需要通過對齊填充來補全。

訪問定位

建立物件是為了使用物件,我們的Java程式需要通過棧上的reference資料來操作堆上的具體物件。

訪問方式

  • 控制程式碼訪問:在堆中劃分出一塊記憶體來作為控制程式碼池,reference中儲存的就是物件的控制程式碼地址,控制程式碼中包含了物件例項資料與型別資料各自的地址資訊。

    深入理解Java虛擬機器之物件的記憶體佈局、訪問定位

  • 直接指標訪問:reference中儲存內容為物件地址。

    深入理解Java虛擬機器之物件的記憶體佈局、訪問定位

兩種訪問方式優勢對比

控制程式碼訪問最大的好處是reference中儲存的是穩定的控制程式碼地址,在物件被移動時只會改變控制程式碼中的例項資料的指標,而無需修改reference本身。

直接指標訪問的最大好處是速凍更快,節省了一次指標定位的時間開銷。

如果讀完覺得有收穫的話,歡迎點贊、關注、加公眾號【Java線上】,查閱更多精彩歷史!!!


相關文章