1. 程式人生 > >Java 對象創建過程

Java 對象創建過程

code har 運行 運行時 分配 hash 成員 應該 線程

對象創建

在語言層面,創建一個對象通常僅一個new關鍵字就可以解決了,但是在虛擬機中,對象的創建要經過一個復雜的過程。

方法區中的常量池

當虛擬機遇到一個new關鍵字時,首先去方法區中的常量池中找有沒有這個類的符號引用,並檢查這個符號代表的類是否已經被加載、解析和初始化過,如果沒有先執行類的加載過程。

堆內存

類加載完成後,接下來在虛擬機中的堆上劃分出一塊內存,存儲類的對象(大小在類加載完成後,根據其內部的變量類型與引用就可以確定類需要的空間大小)。由於GC的機制不同,所以在分配時可能存在兩種機制。

空閑列表法

如果垃圾回收機制為標記清除法那麽虛擬機必須維護一個列表,記錄著哪一塊內存可用,再分配時找到一塊足夠大的空間,劃分給類對象實例。

指針碰撞法

如果垃圾回收機制為復制算法標記整理法,那麽在分配內存時,直接將指針向空閑區域移動一段與對象大小相等的距離即可。

在內存分配時,解決多線程同步的問題,有兩種方案:一種是對分配內從空間的動作做同步處理;另一種是吧內存分配按照線程劃分,即每個線程在Java堆中預先分配一小塊內存,成為本地線程分配緩沖。

內存分配完成後,虛擬機將分配到的內存空間都初始化為零,這一步操作保證了對象中成員對象的初始化。

對象在內存中的存儲結構

對象在內存中的存儲結構可以分為對象頭,實例數據,對齊填充。

對象頭

對象頭中存儲了兩部分信息,一部分存儲對象自身運行時數據,如HashCode,GC分代年齡,鎖狀態標誌等。對象頭的另外一部分存儲著類型指針,指向對象類元數據,虛擬機通過這部分信息確定對象是哪一個類的實例。

如果對象為數組,對象頭中還應該記錄數組的長度。因為不同對象可以通過類的元數據確定對象的大小,但是通過數組的元數據無法得知數組的長度。

實例數據

實例數據部分存儲著對象的有效信息,主要是成員變量。無論是從父類繼承的,還是在子類中定義的都要記錄下來。存儲的順序主要受虛擬機分配策略的影響。

HotSpot中的分配策略為:long/double,int,short/char,byte/boolean,opps(Ordinary Object Pointers)。相同寬度的字段總是被放到一起,在滿足這個條件的情況下,父類中定義的變量總是放到子類之前。

對齊填充

主要因為HotSpot自動內存管理系統要求對象起始地址必須是8字節的整數倍。

Java 對象創建過程