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

jvm-物件的建立過程

在java中使用new建立物件時,虛擬機器建立的過程:

new MyObject();

1、虛擬機器會檢查MyObject這個類是否存在,有沒有被載入。如果MyObject沒有被載入過,那麼就先載入這個類;

2、虛擬機器根據MyObject類的類資訊在堆中分配記憶體空間,分配記憶體有兩種方式:

(1)指標碰撞:當記憶體是規整的,此時有一個指標,在該指標一側的記憶體是已經被分配了,而另一側的記憶體則是空閒的,當建立物件要分配記憶體時,指標向空閒記憶體的一側移動與要建立的物件大小相等的距離,這段距離之間的記憶體就用於存放要建立的物件。

(2)空閒列表:記憶體很少會是規整的,大多都是東一塊西一塊的的破碎記憶體,此時使用一個列表把空閒的記憶體記錄下來,當要建立物件時,找出最合適的一塊空閒記憶體用於儲存這個要建立的物件。

以上兩種方法在單執行緒中是沒有問題的,但是,當處於多執行緒的時候,“指標碰撞”方式,在一個執行緒中建立第一個物件,讀取了指標的地址,正要把指標向空閒記憶體一側移動時,第二個執行緒也要建立第二個物件,此時指標還沒有被修改,所以在第二個執行緒中讀取的指標還是原來的地址,然後分配記憶體也是從那個地址把指標向空閒的一側移動等於第二個物件大小的距離。。。這個時候,第一個執行緒建立的第一個物件,與第二個執行緒建立的第二個物件 會相互覆蓋,資料就會出錯。

而解決方法有兩個:

(1)建立物件的時候進行同步操作,這樣就不會出現多個執行緒讀取到的指標是相同的情況了。。但是,同步會導致效率低下。

(2)使用TLAB本地執行緒分配緩衝,也就是每個執行緒在建立時都先分配一塊堆記憶體用作緩衝,在哪個執行緒建立的物件都在這個執行緒所屬的TLAB中建立物件。

3、分配完物件的記憶體空間後,把這塊記憶體的值置為零置,這樣的話,物件中沒有被初始化的例項欄位就存在初始值了,物件變數欄位初始值為null,基本型別為對應的零值。。

4、初始化物件頭資料,物件頭資料有 執行時資料和型別指標,

    物件頭執行時資料:GC年齡分代、鎖狀態標誌、執行緒持有的鎖、hashcode雜湊碼等。

    型別指標:指向方法區中型別資訊的指標。型別資訊就是編譯後的程式碼以及其他關於這個類的資料資訊。

5、呼叫構造方法進行初始化。