java中物件的建立
我們知道,Java物件例項是由Java執行時資料區的堆所管理的。我們以HotSpot為例,來探討關於Java物件的建立,物件的記憶體佈局,物件的訪問定位
物件的建立:
1、當java虛擬機器遇到new指令時,會通過new指令後的引數到常量池中定位這個類的符號引用,檢查這個符號引用代表的類是否被載入,連線,初始化,如果沒有,則要先執行相應的類載入過程。
2、在類載入檢查通過後,虛擬機器就要為新生物件分配記憶體。記憶體的分配主要有兩種方式:1、指標碰撞,2、空閒列表。
3、記憶體分配完成之後,Java虛擬機器必須將分配到的記憶體(物件頭除外)賦初始值零。這一步保證了物件的例項欄位在Java程式碼中不用賦初始值就可以使用。
4、接下來,Java虛擬機器還會對物件進行一系列的設定。如這個物件是哪個類的例項,如何找到類的元資料資訊,物件的GC分代年齡等資訊。這些資訊存放在物件的物件頭之中。
5、至此,從虛擬機器的角度來看,一個物件的建立已經結束了,但是從Java程式來看,物件的建立剛剛開始——建構函式,即class檔案中的<init>()方法還沒有執行。一般來說,new指令後面會執行<init>()方法,這樣一個真正的物件才被構造出來。
物件的記憶體佈局:
在HotSpot虛擬機器中,物件的記憶體佈局分為三部分:物件頭,例項資料和對齊填充。
物件頭包含兩類資訊:1、用於儲存物件自身的執行時資料,比如雜湊碼、GC分代年齡、鎖狀態標誌等。2、用於儲存型別指標,即物件指向自己型別元資料的指標,Java虛擬機器可以通過這個指標確定物件是哪個類的例項。
例項資料則是物件真正儲存的有效的資訊,即我們在類中所定義的各種型別的欄位,無論是父類所繼承下來的,還是在子類中所定義的。
對齊填充並不是必須存在的,它起著佔位符的作用。
物件的訪問定位:
物件的訪問定位是通過棧中的reference資料來操作堆上的具體物件。主流的訪問方式有兩種:使用控制代碼和直接指標。
控制代碼訪問會在堆上開闢出一塊空間來儲存例項資料和型別資料的各自地址資訊,這塊記憶體空間就是控制代碼池,而reference儲存的就是控制代碼池的地址資訊。
直接指標方式,reference儲存的直接就是物件地址。這種方式需要考慮在物件的記憶體佈局中如何放置型別資料的相關資訊。
參考:《深入理解java虛擬機器》第三版——周志明