深入研究Java虛擬機(jī)的類加載機(jī)制
說到Java虛擬機(jī)的類加載機(jī)制,很多朋友第一反應(yīng)想到的應(yīng)該就是ClassLoader,我也如此,不過ClassLoader其實(shí)只是Java虛擬機(jī)加載機(jī)制中的一部分,最近在看《深入理解Java虛擬機(jī)》,對(duì)Java虛擬機(jī)的類加載機(jī)制有了更深入的了解,不吐不快。
JVM中類的整個(gè)生命周期如下:
加載=》驗(yàn)證=》準(zhǔn)備=》解析=》初始化=》使用=》卸載
使用和卸載這兩個(gè)步驟不在今天的討論范圍之內(nèi),今天我們將著重討論一下前5個(gè)步驟,也就是JVM中類的整個(gè)加載機(jī)制。
1. 加載
類的加載階段,主要是獲取定義此類的二進(jìn)制字節(jié)流,并將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),最后在Java堆中生成一個(gè)代表這個(gè)類的java.lang.Class對(duì)象作為方法區(qū)這些數(shù)據(jù)的訪問入口。
相對(duì)于類加載過程的其他階段,加載階段是開發(fā)期可控性最強(qiáng)的階段。我們可以通過定制不通的類加載器,也就是ClassLoader來(lái)控制二進(jìn)制字節(jié)流的獲取方式。
關(guān)于ClassLoader的介紹,請(qǐng)參照 了解ClassLoader
2. 驗(yàn)證
驗(yàn)證,準(zhǔn)備和解析其實(shí)都屬于連接階段,而驗(yàn)證就是連接階段的第一步。這一階段主要是為了確保Class文件的字節(jié)流中包含的信息復(fù)合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全。
主要驗(yàn)證過程包括:文件格式驗(yàn)證,元數(shù)據(jù)驗(yàn)證,字節(jié)碼驗(yàn)證以及符號(hào)引用驗(yàn)證。
3. 準(zhǔn)備
準(zhǔn)備階段正式為類變量分配內(nèi)存并設(shè)置初始值。這里的初始值并不是初始化的值,而是數(shù)據(jù)類型的默認(rèn)零值。這里提到的類變量是被static修飾的變量,而不是實(shí)例變量。
關(guān)于準(zhǔn)備階段為類變量設(shè)置零值的唯一例外就是當(dāng)這個(gè)類變量同時(shí)也被final修飾,那么在編譯時(shí),就會(huì)直接為這個(gè)常量賦上目標(biāo)值。
4. 解析
解析時(shí)虛擬機(jī)將常量池中的符號(hào)引用替換為直接引用的過程。
5. 初始化
在準(zhǔn)備階段,變量已經(jīng)賦過一次系統(tǒng)要求的初始值,在初始化階段,則是根據(jù)程序員通過程序的主觀計(jì)劃區(qū)初始化類變量和其他資源。
Java虛擬機(jī)規(guī)范規(guī)定了有4種情況必須立即對(duì)類進(jìn)行初始化(加載,驗(yàn)證,準(zhǔn)備必須在此之前完成)
1)當(dāng)使用new關(guān)鍵字實(shí)例化對(duì)象時(shí),當(dāng)讀取或者設(shè)置一個(gè)類的靜態(tài)字段(被final修飾的除外)時(shí),以及當(dāng)調(diào)用一個(gè)類的靜態(tài)方法時(shí),如果類未初始化,則需先初始化。
2)通過反射機(jī)制對(duì)類進(jìn)行調(diào)用時(shí),如果類未初始化,則需先初始化。
3)當(dāng)初始化一個(gè)類時(shí),如果其父類未初始化,先初始化父類
4)用戶指定的執(zhí)行主類(含main方法的那個(gè)類)在虛擬機(jī)啟動(dòng)時(shí)會(huì)先被初始化
除了上面這4種方式,所有引用類的方式都不會(huì)觸發(fā)初始化,稱為被動(dòng)引用。如:通過子類引用父類的靜態(tài)字段,不會(huì)導(dǎo)致子類初始化;通過數(shù)組定義來(lái)引用類,不會(huì)觸發(fā)此類的初始化;引用類的靜態(tài)常量不會(huì)觸發(fā)定義常量的類的初始化,因?yàn)槌A吭诰幾g階段已經(jīng)被放到常量池中了。
總 結(jié):
在上述5個(gè)過程當(dāng)中,驗(yàn)證,準(zhǔn)備和解析完全由Java虛擬機(jī)主導(dǎo)和控制。只要加載階段和初始化階段程序員可以進(jìn)行控制。在加載階段可以通過實(shí)現(xiàn)自定義的ClassLoader來(lái)加載類的二進(jìn)制流,在初始化階段程序員則可完全按照需求來(lái)為類變量賦值。
原文鏈接:http://blog.csdn.net/derekjiang/article/details/7202570
【編輯推薦】