類加載過程
- 加載
- 驗(yàn)證
- 準(zhǔn)備
- 解析
- 初始化
加載
在加載階段屋彪,虛擬機(jī)需要完成3件事情:
1所宰、獲取類的二進(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ù)的訪問入口
數(shù)組的加載有所不同,數(shù)組類本身不通過類加載器創(chuàng)建蟹但,它是由Java虛擬機(jī)直接創(chuàng)建的
驗(yàn)證
這一階段的目的是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求躯泰,并且不會(huì)危害虛擬機(jī)自身的安全,大致上會(huì)完成4個(gè)階段:文件格式驗(yàn)證
华糖、元數(shù)據(jù)驗(yàn)證
麦向、字節(jié)碼驗(yàn)證
、符號(hào)引用驗(yàn)證
客叉。
文件格式驗(yàn)證
驗(yàn)證字節(jié)流是否符合Class文件格式的規(guī)范诵竭,并且能被當(dāng)前版本的虛擬機(jī)處理。該階段的驗(yàn)證的目的主要是保證輸入的字節(jié)流能正確地解析并存儲(chǔ)于方法區(qū)之內(nèi)兼搏,只有通過了這個(gè)階段的驗(yàn)證后卵慰,字節(jié)流才會(huì)進(jìn)入內(nèi)存的方法區(qū)進(jìn)行存儲(chǔ),所以后面3個(gè)階段的驗(yàn)證都是基于方法區(qū)的存儲(chǔ)結(jié)構(gòu)進(jìn)行的佛呻。
元數(shù)據(jù)驗(yàn)證
對(duì)字節(jié)碼描述的信息進(jìn)行語義分析裳朋,以確保其描述符合Java語言規(guī)范的要求。
字節(jié)碼驗(yàn)證
整個(gè)驗(yàn)證過程中最復(fù)雜的一個(gè)階段件相,主要目的是通過數(shù)據(jù)流和控制流分析再扭,確保程序語義是合法的、符合邏輯的夜矗。對(duì)類的方法體進(jìn)行校驗(yàn)分析泛范,保證被校驗(yàn)類的方法在運(yùn)行時(shí)不會(huì)做出危害虛擬機(jī)安全的事件。
符號(hào)引用驗(yàn)證
符號(hào)引用驗(yàn)證可以看作是對(duì)類自身以外(常量池的各種符號(hào)引用)的信息進(jìn)行匹配性校驗(yàn)紊撕。
準(zhǔn)備
準(zhǔn)備階段是正式為類變量(static修飾)分配內(nèi)存并設(shè)置類變量初始值(一般是零值)的階段罢荡,這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配。
解析
解析階段是虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過程。
- 符號(hào)引用:與虛擬機(jī)實(shí)現(xiàn)的內(nèi)存布局無關(guān)区赵,引用的目標(biāo)也不一定已經(jīng)加載到內(nèi)存中惭缰。
- 直接引用:可以是直接指向目標(biāo)的指針、相對(duì)偏移量或一個(gè)能間接定位到目標(biāo)的句柄笼才。直接引用的目標(biāo)必定已經(jīng)加載在內(nèi)存中漱受。
初始化
類加載的最后一步,真正執(zhí)行類中定義的Java程序代碼骡送。初始化過程就是執(zhí)行類構(gòu)造器<clinit>()方法的過程昂羡。
<clinit>()方法是有編譯器自動(dòng)手機(jī)類中所有類變量的賦值動(dòng)作和靜態(tài)代碼塊(static{}塊)中的語句合并產(chǎn)生的,收集順序由語句在源文件出現(xiàn)的順序所決定摔踱,它與類的構(gòu)造函數(shù)(<init>())不同虐先,它不需要顯示調(diào)用父類構(gòu)造器,虛擬機(jī)會(huì)保證子類的<clinit>()方法執(zhí)行之前派敷,父類的<clinit>()方法已經(jīng)執(zhí)行完畢蛹批。