回顧
在學習 Java 執行時的資料區域 之後,我對JVM的記憶體劃分有了比較清晰的輪廓。接下里,我將深入一部分細節——探尋物件建立的過程,建立物件絕非 new Object(); 這麼簡單。
Java 堆
對我來說,Java 堆 是 JVM 的常用記憶體區域,因為 java堆 負責存放物件例項,而我使用 java 程式設計,無時無刻都在和物件打交道。
new
虛擬機器遇到一條 new 指令時:
- 檢查這個指令的引數是否能在常量池中定位到一個類的符號引用,並且檢查這個符號引用代表的類是否已被載入、解析和初始化過
- 類載入檢查通過
- 虛擬機器java堆為新主物件分配記憶體,物件所需記憶體的大小在類載入完成後便可完全確定
- 虛擬機器將分配到的記憶體空間都初始化為零值(不包括物件頭)。所以有時候某些欄位不賦初始值就能直接使用
- 設定物件頭,物件頭中儲存了該物件是拿了類的例項等資訊
- 執行 init 方法(否則所有欄位還為零值),把物件按照程式設計師的意願進行初始化
物件的記憶體佈局
物件在記憶體中儲存的佈局可以分為3塊區域
- 物件頭(Header)
- 例項資料(Instance Data)
對其填充(Padding)
物件頭
物件頭包含兩部分資訊:
- 儲存物件自身的執行時資料
雜湊碼、GC分代年齡、鎖定態標識、執行緒持有鎖等 - 型別指標
即物件指向它的類後設資料的指標,虛擬機器通過這個指標來確定這個物件是哪個類的例項