jvm對象的訪問


對象的內存布局

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

對象頭

對象頭包括如下兩部分信息:

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

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

  • 如果對象是一個數組:對象頭還需要有一塊空間來記錄數組長度,因為對象可以通過類型指針判斷Java對象大小,而數組不行。

實例數據

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

對齊填充

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

對象的訪問

當我們使用對象時,我們需要通過虛擬機棧上的reference數據(即worker)來操作堆上的具體對象。

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

訪問具體對象的方式不同虛擬機有不同的實現,主流的方式有以下兩種

使用句柄池

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

使用直接指針訪問

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

兩種方式的比較

  • 使用句柄池來訪問最大的好處就是reference中存儲的是穩定的句柄地址,在對象被移動(垃圾收集時整體空間位置)時只會改變句柄中的實例數據指針,而reference不需要任何改變。
  • 使用直接指針訪問最大的好處就是快,節省了一次指針定位的時間開銷,由於對象訪問在java中非常頻繁,積少成多,節省這樣的開銷效益非常可觀。
  • 主要虛擬機HotSpot采用直接指針訪問,但是許多其他語言和框架使用句柄這種思想也非常常見。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM