class M{
int n =4;
}
main{
M m = new M();
}
1.對象創建過程
對象初始化過程
1.1申請內存
1.2初始化成員變量 n= 0 //這個時候 m 會指向一個半初始化的對象,因爲n已經初始化
1.3設置初始值 n=4 //m指向一個正確的m對象
2 對象頭具體包括什麼
2.1Mark Word
鎖的信息
Gc標記信息 標記清除算法 GC年齡(4位最大15) 爲什麼標記清除算法標記年齡最大15 對象頭GC標記信息最大4位
hash碼
2.2 klasspointer (指向類的指針) 指向m.class
該指針在32位JVM中的長度是32bit,在64位JVM中長度是64bit。
Java對象的類數據保存在方法區。
2.3 對象內存的存儲佈局
- 普通對象 new object() 包括
markword 對象頭 //8 字節
clas pointer(類型指針) //指向.class
instance data (實例數據) //m
padding(數據對齊) - 數組對象
對象頭
類型指針
數組長度(4字節)
實例數據
對齊
2.4 DCL單例(double check lock) 是否需要volatile 關鍵字
懶漢式單例:
public class Singleton {
private static Singleton singleton;
private Singleton () {}
public static Singleton getInstance () {
if (singleton == null) {
singleton = new Singleton ();
}
return singleton;
}
}
這個在單線程情況下可以保證內存中只存在一個實例,多線程下就不能保證;
所以需要加鎖來解決
public class Singleton {
private static Singleton singleton;
private Singleton () {}
public static synchonized Singleton getInstance () {
//業務代碼
if (singleton == null) {
singleton = new Singleton ();
}
return singleton;
}
這樣加鎖比較重 ,業務代碼也不能執行
優化;
public class Singleton {
private static Singleton singleton;
private Singleton () {}
public static Singleton getInstance () {
if (singleton == null) {
synchonized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton ();
}
}
}
return singleton;
}
}
但是這個有能可會發生指令重排序問題,就是實例在創建過程中,cup會把對象創建幾個步驟重排序執行,;比如兩個線程來實例化 Singleton 對象, a線程只實例化一半時候,只是初始化了 單例中的某個成員變量 n=0 時, 這個時候停止了, b線程進來發現 Singleton 是一個半初始化狀態,是有指向的引用, 就給其返回; 而a繼續執行會實例化一個與b線程不一樣的實例;
這個時候就需要給
private static Singleton singleton; 添加關鍵詞 volatile
.volatile 的特性有
- 線程可見性
所謂“可見性”,是指當一個線程修改了這個變量的值,新值對於其他線程來說是可以立即得知的。(通過主內存,一個線程修改了共享變量,新值立即同步到主內存,其他線程讀取該值時從主內存中拉取)
由於volatile變量只能保證可見性,在不符合以下兩條規則的運算場景中,我們仍然要通過加鎖來保證原子性。
(1)運算結果並不依賴變量的當前值,或者能夠確保只有單一的線程修改變量的值。
(2)變量不需要與其他的狀態變量共同參與不變約束(if(a>b)這種形式)
2. 保證long和double類型變量的原子性。
3. 禁止指令重排序
進而保證有序性。Java中天然的有序性可以總結爲一句話:如果在本線程內觀察,所有的操作都是有序的;如果在一個線程中觀察另一個線程,所有的操作都是無序的。
故最終改進
public class Singleton {
private static volatile Singleton singleton;
private Singleton () {}
public static Singleton getInstance () {
if (singleton == null) {
synchonized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton ();
}
}
}
return singleton;
}
}
2.5 class對象是在堆還是在方法區
創建的Class實例在java heap中
請具體參考 https://www.jianshu.com/p/6e039f83a24b
2.6對象怎麼定位
直接 直接指針
間接 句柄方式
2.7對象內存怎麼分配
當對象大小比較小的時候,直接在棧空間中,對象比較大後,直接進入old區,如果不夠大,進入Eden區 ,GC清理,如果活着,進入survive1, GC再清理,還活着進入survive2,GC繼續清理如果年齡到了進入old區;
2.8 object o = new object();佔多大內存
16字節
最後附一個學習的連接講的很詳細 https://www.jianshu.com/p/76959115d486