Java創(chuàng)建對象的過程
簡單記錄一下Java創(chuàng)建對象的過程哟冬,就是new一個對象的時候發(fā)生了哪些事情洁仗。Java程序執(zhí)行的過程在此不作說明,對象的創(chuàng)建過程只是程序執(zhí)行過程的一部分。有關整個程序執(zhí)行的過程瘩绒,等熟悉了虛擬機之后在作說明。
對象創(chuàng)建過程簡述
Java中對象的創(chuàng)建就是在堆上分配內存空間的過程带族,此處說的對象創(chuàng)建僅限于new關鍵字創(chuàng)建的普通Java對象锁荔,不包括數(shù)組對象的創(chuàng)建。
大致過程如下:
- 檢測類是否被加載
- 為對象分配內存
- 為分配的內存空間初始化零值
- 對對象進行其他設置
- 執(zhí)行init方法
檢測類是否被加載
當虛擬機執(zhí)行到new時蝙砌,會先去常量池中查找這個類的符號引用阳堕。如果能找到符號引用,說明此類已經被加載到方法區(qū)(方法區(qū)存儲虛擬機已經加載的類的信息)择克,可以繼續(xù)執(zhí)行恬总;如果找不到符號引用,就會使用類加載器執(zhí)行類的加載過程肚邢,類加載完成后繼續(xù)執(zhí)行壹堰。
為對象分配內存
類加載完成以后拭卿,虛擬機就開始為對象分配內存,此時所需內存的大小就已經確定了贱纠。只需要在堆上分配所需要的內存即可峻厚。
具體的分配內存有兩種情況:第一種情況是內存空間絕對規(guī)整,第二種情況是內存空間是不連續(xù)的谆焊。
對于內存絕對規(guī)整的情況相對簡單一些目木,虛擬機只需要在被占用的內存和可用空間之間移動指針即可,這種方式被稱為指針碰撞懊渡。
對于內存不規(guī)整的情況稍微復雜一點刽射,這時候虛擬機需要維護一個列表,來記錄哪些內存是可用的剃执。分配內存的時候需要找到一個可用的內存空間誓禁,然后在列表上記錄下已被分配,這種方式成為空閑列表肾档。
分配內存的時候也需要考慮線程安全問題摹恰,有兩種解決方案:
- 第一種是采用同步的辦法,使用CAS來保證操作的原子性怒见。
- 另一種是每個線程分配內存都在自己的空間內進行俗慈,即是每個線程都在堆中預先分配一小塊內存,稱為本地線程分配緩沖(TLAB)遣耍,分配內存的時候再TLAB上分配闺阱,互不干擾。
為分配的內存空間初始化零值
對象的內存分配完成后舵变,還需要將對象的內存空間都初始化為零值酣溃,這樣能保證對象即使沒有賦初值,也可以直接使用纪隙。
對對象進行其他設置
分配完內存空間赊豌,初始化零值之后,虛擬機還需要對對象進行其他必要的設置绵咱,設置的地方都在對象頭中碘饼,包括這個對象所屬的類,類的元數(shù)據(jù)信息悲伶,對象的hashcode艾恼,GC分代年齡等信息。
執(zhí)行init方法
執(zhí)行完上面的步驟之后拢切,在虛擬機里這個對象就算創(chuàng)建成功了蒂萎,但是對于Java程序來說還需要執(zhí)行init方法才算真正的創(chuàng)建完成,因為這個時候對象只是被初始化零值了淮椰,還沒有真正的去根據(jù)程序中的代碼分配初始值,調用了init方法之后,這個對象才真正能使用主穗。
到此為止一個對象就產生了泻拦,這就是new關鍵字創(chuàng)建對象的過程。過程如下:
檢測類是否被加載-->為對象分配內存空間-->初始零值-->進行必要的設置-->調用init方法進行初始化忽媒。