1. 程式人生 > >深入理解Java虛擬機器學習筆記2-JVM中物件佈局

深入理解Java虛擬機器學習筆記2-JVM中物件佈局

一、物件的記憶體佈局

在Hotspot中,物件在記憶體中儲存佈局可以分為三塊: 物件頭(Header) 、例項資料(Instance Data)、對齊填充(Padding)

二、物件頭

1、物件執行時資料: 雜湊嗎、GC分代年齡、鎖狀態標誌、執行緒持有的鎖、偏向執行緒ID、偏向時間戳;官方成為MarkWord,一種非固定資料結構,根據物件狀態標誌位複用儲存空間儲存物件資料的結構。

2、型別指標:指向類元資料的指標

三、例項資料

物件真正儲存的有效資訊,也就是程式碼中定義各種型別的欄位內容。

四、對齊填充

Hotspot虛擬機器自動記憶體管理系統要求物件起始地址必須是8位元組的整數倍,因此物件的大小必須是8位元組的整數倍。當物件例項資料沒有對齊時候,需要通過對齊填充補全。

五、記憶體中物件的建立

1. new一個物件  --首先檢查執行時常量池中是否能定位這個類的符號引用,並檢查這個符號引用代表的類,是否已被載入、解析、初始化過。如果沒有,進行類載入。

2.類載入通過後,虛擬機器為新生物件分配記憶體。物件所需的記憶體大小在類載入後便可以確定。java堆中分配記憶體,有兩種方式,指標碰撞和空閒列表,方式的選擇,取決於堆是否規整,對是否規整取決於採用垃圾收集器是否帶有壓縮整理功能決定。因此Serial ParNew 等帶compact過程的收集器,採用指標碰撞,CMS這種基於Mark-Sweep演算法的垃圾收集器,採用空閒列表。

3.記憶體分配完畢,虛擬機器需要將分配到記憶體空間都初始化零值。保證物件例項欄位在java程式碼中,不被賦初始化就可以被直接使用。

4.再下一步,虛擬機器對物件進行必要的設定,例如物件是哪個類的例項,如果才能找到類的元資料資訊、物件的雜湊碼、物件的GC分代年齡等,還有根據當前執行狀態,是否啟用偏向鎖等。

5.到這一步,從虛擬機器視角看,一個物件產生完畢,但是從程式設計師角度看,才剛剛開始,<init> 方法還沒有執行,所有欄位都還為零。一般執行new指令之後,會接著執行<init>方法,自定義初始化完成。

注意:在第2步,分配記憶體,為了保證併發情況下對同一塊記憶體分配的執行緒安全,有兩種方式,一種是為每個執行緒分配一小塊記憶體,成為本地執行緒分配緩衝TLAB。啟用的話(引數-XX:+UseTLAB開啟TLAB),預設是開啟的,物件先在TLAB上分配,TLAB不夠用,才會鎖定,提升效率。另外一種是採用CAS配上失敗重試的方式,保證分配記憶體更新指標操作的原子性。

六、物件的訪問定位

1.使用控制代碼

2.使用指標

使用控制代碼的優點是,棧幀本地變量表中儲存的reference是穩定控制代碼地址,物件被移動時,只改變控制代碼中例項資料指標,在物件移動時候,只需改變控制代碼中例項資料指標,而reference不需要修改,適用於垃圾收集時候移動物件非常普遍的情況下。

使用指標最大好處就是速度快,使用控制代碼需要reference定位控制代碼池中資料,再指向堆中物件,但是直接指標,直接從棧幀本地區域性變量表中reference指向堆中物件,在訪問java物件比較頻繁的情況下,可以節省一次指標定位時間開銷,積小成多效率可觀。Hotspot使用直接指標。

tips:發現一個寫的比較好的,物件建立時候記憶體分配過程描述文章~~