jvm對象的訪問

對象的內存佈局

在 HotSpot虛擬機中,對象在內存中存儲的佈局分爲三塊區域:對象頭,實例數據,和對齊填充。java

對象頭

對象頭包括以下兩部分信息:數組

  • MarkWord:用於存儲對象自身的運行時數據,如哈希碼、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等。爲了在極小空間內存儲更多的信息,它被設計成了一個非固定的數據結構,根據對象的狀態來複用本身的存儲空間,以下:數據結構

    存儲內容 標誌位 狀態
    對象哈希碼、分代年齡 01 未鎖定
    指向鎖記錄的指針 00 輕量級鎖定
    指向重量級鎖的指針 10 膨脹(重量級鎖定)
    11 GC標記
    偏向線程ID\偏向時間戳、分代年齡 01 可偏向
  • 類型指針:到對象類型數據的指針,即虛擬機經過這個指針來肯定這個對象屬於哪一個類。(有的虛擬機經過句柄池來實現)框架

  • 若是對象是一個數組:對象頭還須要有一塊空間來記錄數組長度,由於對象能夠經過類型指針判斷Java對象大小,而數組不行。佈局

實例數據

是對象真正的有效數據,也就是代碼中所定義的各類類型的字段內容,不管是從父類繼承仍是子類記錄的都必須進行存儲。ui

對齊填充

對齊填充並非必然存在的,也沒有其它的意義,僅僅是佔位符的做用,由於HotSpot虛擬機的自動內存管理系統要求對象地址必須是8的整數倍,當實例數據沒有對齊時,就須要對齊填充來進行補齊。線程

對象的訪問

當咱們使用對象時,咱們須要經過虛擬機棧上的reference數據(即worker)來操做堆上的具體對象。設計

public Worker buildWorker(){
	Worker woker = new Woker();
	worker.setAge(21);
	....
	return worker;
}

訪問具體對象的方式不一樣虛擬機有不一樣的實現,主流的方式有如下兩種指針

使用句柄池

在Java堆中專門劃分處一部份內存做句柄池,reference中存儲的是對應對象的句柄地址,而句柄池中包含了對象實例數據類型數據具體的地址信息,以下圖:code

使用直接指針訪問

直接指針訪問,reference中直接存儲對象地址。

兩種方式的比較

  • 使用句柄池來訪問最大的好處就是reference中存儲的是穩定的句柄地址,在對象被移動(垃圾收集時總體空間位置)時只會改變句柄中的實例數據指針,而reference不須要任何改變。
  • 使用直接指針訪問最大的好處就是快,節省了一次指針定位的時間開銷,因爲對象訪問在java中很是頻繁,聚沙成塔,節省這樣的開銷效益很是可觀。
  • 主要虛擬機HotSpot採用直接指針訪問,可是許多其餘語言和框架使用句柄這種思想也很是常見。
相關文章
相關標籤/搜索