Java對象

1. 對象的創建

  1. 類加載

    虛擬機遇到一條new指令時,首先檢查這個指令的參數是否能在常量池中定位到一個類到符號引用,並檢查這個符號引用代表到類是否已經被加載、解析和初始化。如果沒有,那必須先執行相應的類加載過程。

  2. 分配內存

    接下來虛擬機將爲新生對象分配內存。對象所需內存的大小在類加載完成後便可完全確定,爲對象分配空間的任務等同於把一塊確定大小的內存從Java堆中劃分出來。

  3. 內存初始化

    內存分配完成後,虛擬機需要將分配到到內存空間都初始化爲零值(不包括對象頭)。這一步驟操作保證了對象都實例字段在Java代碼中可以不賦值就直接使用,程序能訪問到這些字段到數據類型所對應的零值。

  4. 對象頭設置

    接下來,虛擬機要對對象進行必要對設置,例如這個對象是那個類對實例、如何才能找到類對元數據信息、對象對哈希碼、對象對GC分代年齡等信息。這些對象存放在對象頭(Object Header)之中。

  5. init方法

    一般來說,執行new指令後會接着執行<init>方法,把對象按照程序員的意願進行初始化。

2. 對象的內存佈局

在HotSpot虛擬機中,對象在內存中的存儲的佈局可以分爲3塊區域:對象頭(Object Header)、實例數據(Instance Data)和對齊填充(Padding)。

  1. 對象頭

    HotSpot虛擬機的對象頭分兩部分,第一部分用於存儲對象自身的運行時數據,如哈希碼、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等。

    第二部分是類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。另外,如果對象是一個Java數組,那在對象頭中還必須有一塊用於記錄數組長度的數據,因爲虛擬機可以通過普通Java對象的元數據信息確定Java對象的大小,但是從數組的元數據中無法確定數組的大小。

  2. 實例數據

    實例數據是對象真正存儲的有效信息,也是在程序代碼中所定義的各種類型的字段內容。

  3. 對齊填充

    不是必須的,也沒有特別含義,它僅僅起着佔位符的作用,HotSpot VM要求對象大小必須是8字節的整數倍。

3. 對象的訪問定位

我們的Java程序需要通過棧上的reference數據來操作堆上的具體對象。目前主流的訪問方式有使用句柄和直接指針兩種。

  1. 句柄訪問
    Java堆中劃分出一塊內存來作爲句柄池,reference中存儲的就是對象的句柄地址,而句柄中包含了對象實例數據與類型數據各自的具體地址信息,如下圖:

image

  1. 直接指針訪問

    如果使用直接指針訪問,那麼Java堆對象的佈局中就必須考慮如何放置訪問類型數據相關的信息,而reference中存儲的直接就是對象地址。如下圖:

image

HotSpot使用第二種方式進行對象的訪問。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章