在 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中直接存儲對象地址。