類加載機(jī)制
本文主要是對(duì)java中類加載機(jī)制的入門級(jí)別文章,主要介紹類加載機(jī)制基本概念,以及類加載機(jī)制主要內(nèi)容。本文按照結(jié)構(gòu)組織如下:
- 類加載機(jī)制是什么
- 類加載機(jī)制主要內(nèi)容
一丶類加載機(jī)制什么?

java程序從靜態(tài)文本到動(dòng)態(tài)執(zhí)行的過程
????java中的類加載機(jī)制,從字面意思就不難理解。就是描述class文件加載到j(luò)vm的主要過程,class文件是對(duì)java類的描述,加載java類的過程就是加載class文件的過程。
????類加載機(jī)制是圍繞ClassLoader這個(gè)核心類展開的,classLoader就是類加載機(jī)制中的核心類。classLoader有如下幾個(gè)主要的方法:

classLoader的核心方法.png
- defineClass:是將字節(jié)碼加載到JVM內(nèi)存中,解析成Class對(duì)象的方法。
- findClass: 該方式解析指定路徑下的class文件生成Class對(duì)象的方法。一般defineClass方法和findClass是組合使用的,在findClass方法中依據(jù)指定路徑,獲取字節(jié)流,然后代用defineClass方法進(jìn)行解析。
- resolveClass:解析繼承關(guān)系上的的父類,以及所引用的類,是一個(gè)遞歸解析的過程,在對(duì)象正真被實(shí)例化的時(shí)候,該方法被調(diào)用。
- loadClass:該方法是上述所有方法的一站式解決方案,也是JVM自帶類加載機(jī)制。如果調(diào)用loadClass方法加載類,是按照J(rèn)VM默認(rèn)的規(guī)則加載類,如果需要定制類加載器,則通過重寫上述的三個(gè)方法可以達(dá)到效果
二丶類加載記住的主要內(nèi)容
1. 誰(shuí)來(lái)負(fù)責(zé)class文件的加載
在java代碼中,每個(gè)定義的類都是由classloader加載進(jìn)來(lái)的。JVM中的類加載器之間的關(guān)系組織結(jié)構(gòu)和類的繼承關(guān)系有些相似,都是一層層的,一個(gè)類加載器有父加載器,父加載器下面有許多子加載器。JVM主要提供三層類加載器:
1.1 類加載器組織結(jié)構(gòu)
- 第一層:Bootstrap ClassLoader,這個(gè)類加載器,主要復(fù)雜加載JVM自身工作所需要的類。其他人都訪問不到這個(gè)類加載器,是一個(gè)相對(duì)獨(dú)立的類加載,其上沒有父加載器,也沒有子加載器
- 第二層:ExtClassLoader,這類加載是應(yīng)用層能夠訪問到的頂層類加載器,可以認(rèn)為其沒有父加載器,只有子加載器。其主要負(fù)責(zé)加System.getProperty("java.ext.dirs")目錄下的類。
-第三層:AppClassLoader,這個(gè)類加載器就是我們最常接觸的類加載器,用來(lái)接在classpath路徑下類的加載器。其父加載器是ExtClassLoader.
特別注意,從邏輯上可以定義第四層類加載器: - 第四層:自定義classLoader,該層不是JVM自帶的類加載器,而是我們自定義的類加載器,在整個(gè)類加載的組織結(jié)構(gòu)中,可以理解為第四層,其父加載器是AppClassLoader.
在熟悉類加載器組織結(jié)構(gòu)后,我們還不能回答究竟是誰(shuí)負(fù)責(zé)加載java類。在介紹完上級(jí)委托加載機(jī)制(雙親委托加載機(jī)制)后,就可以從眾多classLoader中找到合適的類加載器加載java類了。類加載器的組織結(jié)構(gòu)
1.2 上級(jí)委托加載機(jī)制

上級(jí)委托加載機(jī)制
圖中的類加載器1是類加載器2的父加載器,從上往下依次類推。
- 向上詢問:當(dāng)我們使用類加載器4加載目標(biāo)對(duì)象時(shí),并不一定是類加載器4來(lái)負(fù)責(zé)該類的加載,類加載器4在確保目標(biāo)類未被加載后,會(huì)將加載請(qǐng)求傳遞給其父加載器classloader3。classloader3會(huì)繼續(xù)重復(fù)和classloader4相同的工作,向其父加載器傳遞加載請(qǐng)求,加載請(qǐng)求最后被傳遞給頂層加載器classloader1.。在該過程中如果某層加載器發(fā)現(xiàn)該類已加載了,則結(jié)束加載過程,確保不重復(fù)加載。如果頂層加載機(jī)制受理了加載請(qǐng)求,此次加載過程就結(jié)束了。**這個(gè)過程,
- 向下委派 如果頂層加載機(jī)制不受理該次加載請(qǐng)求,其會(huì)將類加載請(qǐng)求按原路遣返,沿途加載器將會(huì)依次檢查是否受理該次類加載請(qǐng)求,最后由受理加載器加載目標(biāo)類。
二丶類加載過程
上級(jí)委托機(jī)制回答了是誰(shuí)負(fù)責(zé)加載類的這個(gè)問題,閱讀完這一節(jié)后,就可以回答JVM加載類的一般過程了。

JVM加載類的階段
- 第一階段:該階段的主要工作是定義去哪兒找class文件,并且通過字節(jié)流的形式將class文件加載到內(nèi)存中。
- 第二階段:該階段細(xì)分為三個(gè)小階段
- 字節(jié)碼驗(yàn)證:類加載對(duì)加載的字節(jié)碼,要做許多驗(yàn)證,確保class文件格式正確,行為正確。
- 類準(zhǔn)備:在該階段準(zhǔn)備描述類中字段,方法以及實(shí)現(xiàn)接口所需要的數(shù)據(jù)結(jié)構(gòu),
- 解析:在這個(gè)階段類加載器會(huì)將類中引用的所有相關(guān)類都加載進(jìn)去,并且這是一個(gè)遞歸的過程。
- 第三階段:初始化class對(duì)象,在這個(gè)階段靜態(tài)變量將初始化,靜態(tài)代碼塊也是在這個(gè)時(shí)候執(zhí)行的。
三丶定制類加載器
了解類加載機(jī)制的基本原理后,我們可以看看類加載機(jī)制在實(shí)際開發(fā)中的一些用途
- 在自定義路徑下查找class類文件,當(dāng)我們需要的class文件,不是在classpath路徑下時(shí),就需要自己實(shí)現(xiàn)一個(gè)類加載器來(lái)加載指定路徑下的class文件。
- 對(duì)要加載的類做特殊的處理,在網(wǎng)絡(luò)傳輸類信息時(shí),一般會(huì)對(duì)類的字節(jié)碼加密。在加載到JVM之前需要對(duì)類的字節(jié)碼解密后再按傳統(tǒng)方法加載,這個(gè)過程就可以通過自定義類加載器實(shí)現(xiàn)
- 類加載器一個(gè)比較常見的應(yīng)用就是熱部署,檢查到已經(jīng)加載的class文件已經(jīng)修改的時(shí)候,重新加載這個(gè)類,以實(shí)現(xiàn)熱部署。
