? ? ? ?虛擬機(jī)把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存怎燥,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)呼股、轉(zhuǎn)換、解析和初始化晨川,最終形成可以被虛擬機(jī)直接使用的Java類型证九,這就是虛擬機(jī)的類加載機(jī)制。
1. 類的加載時(shí)機(jī)
上圖中共虑,加載愧怜,驗(yàn)證,準(zhǔn)備妈拌,初始化和卸載這五個(gè)階段的順序是確定的拥坛,而解析階段則不一定,可以在初始化之前尘分,也可以在初始化之后猜惋,這是為了支持運(yùn)行時(shí)綁定。
接口與類初始化過(guò)程的不同點(diǎn):當(dāng)一個(gè)類在初始化時(shí)培愁,要求其父類 全部都已經(jīng)初始化著摔,但一個(gè)接口并不要求其父接口全部都初始化,只有在真正使用到父接口的時(shí)候才會(huì)初始化定续。
2. 類加載的過(guò)程
1. 加載:在加載過(guò)程中虛擬機(jī)需要完成以下三件事:
? ? 1)通過(guò)一個(gè)類的全限定名來(lái)獲取定義此類的二進(jìn)制字節(jié)流谍咆;
? ? 2)將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu);
? ?3)在內(nèi)存中生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象香罐,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問(wèn)入口卧波;
2. 驗(yàn)證:連接階段的第一步,為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求庇茫,并且不會(huì)危害虛擬機(jī)自身的安全港粱。包括以下驗(yàn)證:
? ? 1)文件格式的驗(yàn)證:魔數(shù)版本號(hào)之類的
? ? 2)元數(shù)據(jù)的驗(yàn)證:驗(yàn)證類與父類之間的關(guān)系,對(duì)類的元數(shù)據(jù)進(jìn)行語(yǔ)義校驗(yàn)
? ? 3)字節(jié)碼驗(yàn)證:最復(fù)雜的階段,通過(guò)數(shù)據(jù)流和控制流分析查坪,確定程序語(yǔ)義是合法的寸宏,符合邏輯的,對(duì)類的方法體進(jìn)行校驗(yàn)分析偿曙。
? ? 4)符號(hào)引用驗(yàn)證:對(duì)類自身以外(常量池中的各種符號(hào)引用)的信息進(jìn)行匹配性校驗(yàn)氮凝,主要發(fā)生在虛擬機(jī)將符號(hào)引用轉(zhuǎn)化為直接引用的時(shí)候。
3. 準(zhǔn)備:正式為類變量分配內(nèi)存并設(shè)置類變量初始值的階段望忆,都將在方法區(qū)進(jìn)行分配罩阵,只包括類變量,不包括實(shí)例變量启摄,而這里說(shuō)的初始值通常情況下稿壁,是數(shù)據(jù)類型的零值。如果類字段的字段屬性表中存在ConstantValue屬性(即是final的)歉备,就被會(huì)初始化為指定的值傅是。
4. 解析:解析階段是虛擬機(jī)將虛擬機(jī)常量池的符號(hào)引用替換為直接引用的過(guò)程。包括以下幾種情況:
? ? 1)類或接口的解析
? ? 2)字段解析
? ? 3)類方法解析
? ? 4)接口方法解析
5. 初始化:此階段才真正開(kāi)始執(zhí)行類中定義的Java程序代碼(或者說(shuō)是字節(jié)碼)