1. 程式人生 > >物件建立過程

物件建立過程

物件的建立過程:
1.指令引數能否在常量池中定位到一個類的符號引用;
2.檢查這個符號引用代表的類是否已經被載入、解析和初始化,如果沒有必須先執行類載入過程;
3.類載入檢查通過後,虛擬機器分配記憶體(物件的記憶體大小在類載入完成後就可以確定)。記憶體分配有“指標碰撞”和“空閒列表”兩種方式。
首先先解釋一下“指標碰撞”–假設java堆記憶體是絕對完整的,那麼用過的記憶體放在一邊,空閒的記憶體放在一邊,中間放著一個指標作為
分界點指示器,那麼分配記憶體的時候就是把指標向空閒記憶體那邊挪動物件大小等距離的位置。
“空閒列表”是指java堆的記憶體是不規整的,已使用的記憶體和空閒記憶體是交叉存在的,那就沒有辦法簡單的進行“指標碰撞”了,
虛擬機器就需要維護一個列表,這個列表上記錄了那些記憶體是可用的,在分配時從列表物件中劃分一塊足夠大的空間劃分給物件例項,並更新表上的例項。
java堆是否規則是由所採用的gc是否帶有壓縮整理功能決定的。
4.除了劃分可用空間外,還需考慮物件建立在虛擬機器中是否頻繁出現,因為在併發環境下即使僅僅修改一個指標所指向的位置也不是執行緒安全的


例如我正在給A物件分配記憶體,指標還沒來得及修改,物件B又使用了原來的指標)。
兩種解決方案:一、對分配記憶體空間的動作進行同步處理–實際上就是虛擬機器採用CAS配上失敗重試的方式保證更新操作的原子性;
二、把記憶體分配動作劃分給不同空間執行,即每個執行緒在java堆中預先分配一小塊記憶體,稱為本地執行緒分配緩衝。哪個執行緒要分配記憶體,
就在哪個執行緒的TLAB上分配,只有TLAB用完並重新分配新的TLAB時,才需要同步鎖定。可以使用-XX:+/-UserTLAB引數來設定。
5.記憶體分配完成後,虛擬機器需要將分配到的記憶體初始化為零值(不包括物件頭),如果使用TLAB,這一工作需要提前至TLAB分配時進行。
這一操作保證了物件例項欄位可以在java程式碼中不賦初始值直接使用,程式能訪問到這些欄位所對應的零值。
6.**接下來需要一些必要的設定,例如這個物件時哪個類的例項、如何才能找到元資料資訊、物件的雜湊嗎、物件的GC分代年齡等資訊。
這些資訊都存放在物件的物件頭之中。**
7.上面工作完成後,從虛擬機器視角來看,一個新的物件已經產生,但從java程式的視角來看,物件建立才剛剛開始–方法還沒執行,所有欄位都還是零。
一般來說執行new之後戒指執行方法,把物件按照程員的意願進行初始化,這樣一個真正的可用物件才算完全產生出來。