1. 程式人生 > >java虛擬機之對象的創建與內存布局

java虛擬機之對象的創建與內存布局

任務 線程安全 對象分配 開始 修改 strong 劃分 整理 完成後

  對象的創建大致過程:

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

    在類加載檢查通過以後,接下來將為新生對象分配內存。對象所需內存的大小在類加載完成後便可完全確定。為對象分配空間的任務等同於把一塊確定大小的內存從Java堆中劃分出來。為對象分配空間的任務等同於把一塊確定大小的內存從Java堆中劃分出來。分配方式:指針碰撞、空閑列表。選擇哪種分配方式由Java堆是否規整決定,而java堆是否規整又由所采用的垃圾收集器是否帶有壓縮整理功能決定。 另外還需要考慮的問題是對象創建在虛擬機中是否是非常頻繁的行為,即使是僅僅修改一個指針所指向的位置,在並發情況下也不是線程安全的。有兩種解決方案:1、對分配內存空間的動作進行同步處理 2、把內存分配的動作按照線程劃分在不同的空間中進行。

    在內存分配完成後,虛擬機需要將分配到的內存空間都初始化為零值(不包括對象頭)

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

    現在,對虛擬機來說,新的對象已經產生,但對java程序來說,對象才剛剛開始,因為還沒有執行init方法。

  對象的內存布局

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

    對象頭包括兩部分的信息:1、用於存儲對象自身的運行時數據:如哈希碼,GC分代年齡,鎖狀態標誌,線程持有的鎖,偏向線程ID,偏向時間戳。2 、存儲類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例。【3、如果對象是一個Java數組,那麽在對象頭中還必須有一塊用於記錄數組長度的數據,因為虛擬機可以通過普通Java對象的元數據信息來確定Java對象的大小,但是從數組的元數據中卻無法確定數組的大小】

java虛擬機之對象的創建與內存布局