文章目錄
解釋一下對象的創建過程(半初始化)
-
Object o = new Object();
- new Object()先在內存中申請空間,創建出對象,半初始化;
- o在main方法棧幀中產生,存放堆中對象的內存地址;
- 最後指針指向堆對象,建立關聯。
詳細參考:圖解JAVA對象的創建過程
DCL單例到底需不需要加volatile?(單例模式,指令重排)
- DCL:double check lock雙重檢測鎖;
- 用volatile修飾的對象,會禁止對該對象存儲位置操作的指令重排。
- 通過問題一我們知道對象創建分爲三個步驟,這三個步驟之間有可能會發生指令重排。多線程條件下,一個線程操作對象:執行完半初始化,下一步可能會先建立連接再執行對象的init方法,另一個線程可能會在對象建立完連接便提取對象,此時對象處於半初始化狀態。
- volatile:禁止指令重排,會避免使用到半初始化狀態的對象。
對象在內存中的存儲佈局(對象和數組的存儲不同)
對象頭包括什麼?(Markword,class pointer)
- markword:hashcode、gc、鎖信息(讀hotspot源碼)(8個字節)
- class pointer 指向類對象(開啓壓縮4個字節,不壓縮8個字節)
對象怎麼定位?(直接、間接)
-
hotsopot的具體實現,實現方式是直接指針。
-
句柄(間接)方式:方便gc操作,GC需要經常移動對象。
對象怎麼分配?(棧上-線程本地-Edum-Old)
- jvm讀到new關鍵字,首先會嘗試在棧上分配對象(經過逃逸分析和標量計算),棧上創建對象的好處:棧內對象出棧之後,生命週期結束,不需要GC介入。。
- TLAB:thread local allcation buffer 線程本地分配緩衝區,管理線程的分配競爭。
Object o = new Object()在內存中佔多少個字節?
=右邊:
-
class pointer: 指向類對象(開啓壓縮4個字節,不壓縮8個字節)
-
markword:hashcode、gc、鎖信息(讀hotspot源碼)(8個字節)
-
instance data:按數據量變化,沒有則爲0字節
-
最後對齊(被8整除)
=左邊:
- o也佔用空間,壓縮4個字節,不壓縮8個字節。
爲什麼hotspot不使用c++對象來代表java對象?
- vritual pointer虛函數表的指針在c++有,在java沒有。