對象建立的流程步驟包括哪些
- 虛拟機遇到一條new指令時,首先檢查這個對應的類能否在常量池中定位到一個類的符号引用
- 判斷這個類是否已被加載、解析和初始化
- 為這個新生對象在Java堆中配置設定記憶體空間
Java堆配置設定記憶體空間的方式主要有以下兩種
指針碰撞空閑清單
- 配置設定記憶體空間包括開辟一塊記憶體和移動指針兩個步驟
- 非原子步驟可能出現并發問題,Java虛拟機采用CAS配上失敗重試的方式保證更新操作的原子性
- 配置設定記憶體空間包括開辟一塊記憶體和修改空閑清單兩個步驟
- 非原子步驟可能出現并發問題,Java虛拟機采用CAS配上失敗重試的方式保證更新操作的原子性
- 将配置設定到的記憶體空間都初始化為零值
- 設定對象頭相關資料
- GC分代年齡
- 對象的哈希碼 hashCode
- 中繼資料資訊
- 執行對象
方法<init>
對象的資料結構
對象頭
1)對象頭用于存儲對象的中繼資料資訊,包括對象運作時資料和類型指針
2)Mark Word 部分資料的長度在32位和64位虛拟機(未開啟壓縮指針)中分别為32bit和64bit,存儲對象自身的運作時資料如哈希值等。Mark Word一般被設計為非固定的資料結構,以便存儲更多的資料資訊和複用自己的存儲空間
3)類型指針:指向它的類中繼資料的指針,用于判斷對象屬于哪個類的執行個體
- 執行個體資料存儲的是真正有效資料,如各種字段内容,各字段的配置設定政策為longs/doubles、ints、shorts/chars、bytes/boolean、oops(ordinary object pointers),相同寬度的字段總是被配置設定到一起,便于之後取資料。父類定義的變量會出現在子類定義的變量的前面
- 對齊填充部分僅僅起到占位符的作用
對象通路的定位方式
當我們在堆上建立一個對象執行個體後,就要通過虛拟機棧中的reference類型資料來操作堆上的對象
現在主流的通路方式有兩種(HotSpot虛拟機采用的是第二種)
- 使用句柄通路對象。即reference中存儲的是對象句柄的位址,而句柄中包含了對象執行個體資料與類型資料的具體位址資訊,相當于二級指針
2.直接指針通路對象。即reference中存儲的就是對象位址,相當于一級指針
對比
垃圾回收方式分析
方式1當垃圾回收移動對象時,reference中存儲的位址是穩定的位址,不需要修改,僅需要修改對象句柄的位址;
方式2垃圾回收時需要修改reference中存儲的位址
通路效率分析
方式2優于方式1,因為方式2隻進行了一次指針定位,節省了時間開銷,而這也是HotSpot采用的實作方式