簡述一下 Java 中創建一個對象的過程?
類的生命周期
解析:回答這個問題首先就要清楚類的生命周期
下圖展示的是類的生命周期流向:
Java中對象的創建就是在堆上分配內存空間的過程,此處說的對象創建僅限於new關鍵字創建的普通Java對象,不包括數組對象的創建。
對象創建過程
1.檢測類是否被加載:
當虛擬機執行到new時,會先去常量池中查找這個類的符號引用。如果能找到符號引用,說明此類已經被加載到方法區(方法區存儲虛擬機已經加載的類的信息),可以繼續執行;如果找不到符號引用,就會使用類加載器執行類的加載過程,類加載完成后繼續執行。
2.為對象分配內存:
類加載完成以后,虛擬機就開始為對象分配內存,此時所需內存的大小就已經確定了。只需要在堆上分配所需要的內存即可。
具體的分配內存有兩種情況:第一種情況是內存空間絕對規整,第二種情況是內存空間是不連續的。
- 對於內存絕對規整的情況相對簡單一些,虛擬機只需要在被占用的內存和可用空間之間移動指針即可,這種方式被稱為指針碰撞。
- 對於內存不規整的情況稍微復雜一點,這時候虛擬機需要維護一個列表,來記錄哪些內存是可用的。分配內存的時候需要找到一個可用的內存空間,然后在列表上記錄下已被分配,這種方式成為空閑列表。
分配內存的時候也需要考慮線程安全問題,有兩種解決方案:
- 第一種是采用同步的辦法,使用CAS來保證操作的原子性。
- 另一種是每個線程分配內存都在自己的空間內進行,即是每個線程都在堆中預先分配一小塊內存,稱為本地線程分配緩沖(TLAB),分配內存的時候再TLAB上分配,互不干擾。
3.為分配的內存空間初始化零值:
對象的內存分配完成后,還需要將對象的內存空間都初始化為零值,這樣能保證對象即使沒有賦初值,也可以直接使用
4.對對象進行其他設置:
分配完內存空間,初始化零值之后,虛擬機還需要對對象進行其他必要的設置,設置的地方都在對象頭中,包括這個對象所屬的類,類的元數據信息,對象的hashcode,GC分代年齡等信息。
5.執行 init 方法:
執行完上面的步驟之后,在虛擬機里這個對象就算創建成功了,但是對於Java程序來說還需要執行init方法才算真正的創建完成,因為這個時候對象只是被初始化零值了,還沒有真正的去根據程序中的代碼分配初始值,調用了init方法之后,這個對象才真正能使用。
到此為止一個對象就產生了,這就是new關鍵字創建對象的過程。過程如下
參考文章:Java創建對象的過程簡介 -----》