1.當(dāng)AppClassLoader去加載一個(gè)class時(shí),它首先不會(huì)自己去嘗試加載這個(gè)類,而是把類加載請(qǐng)求委托給父加載器ExtClassLoader去完成。
2.當(dāng)ExtClassLoader去加載一個(gè)class時(shí),它首先也不會(huì)去嘗試加載這個(gè)類,而是把類加載請(qǐng)求委托給父加載器BootstrapClassLoader去完成。
3.如果BootstrapClass加載失?。ɡ缭贘AVA_HOME/jre/lib里未找到該class),就會(huì)使用ExtClassLoader來(lái)嘗試加載。
4.如果使用ExtClassLoader加載失?。ɡ缭贘AVA_HOME/jre/lib/ext里未找到該class),就會(huì)使用AppClassLoader來(lái)嘗試加載。如果AppClassLoader也加載失敗,則會(huì)拋出異常ClassNotFoundException。
從代碼層面了解幾個(gè)Java中定義的類加載器及雙親委派模型的實(shí)現(xiàn),他們的類圖關(guān)系如下。
從圖可以看出頂層的類加載器是抽象類abstract ClassLoader
,其后所有的類加載器都繼承自ClassLoader(不包括啟動(dòng)類加載器)。
為了更好的理解雙親委派模型,ClassLoader源碼中的loadClass(String)方法該方法加載指定名稱(包括包名)的二進(jìn)制類型,該方法在jdk1.2后不建議用戶重寫但是可以直接調(diào)用該方法。loadClass()方法是ClassLoader類自己實(shí)現(xiàn)的,該方法中的邏輯就是雙親委派模式的實(shí)現(xiàn)。
loadClass(String name, boolean resolve)是一個(gè)重載方法,resolve參數(shù)代表是否生成Class對(duì)象的進(jìn)行解析相關(guān)的操作,源碼分析如下。
雙親委派模型意義總結(jié)來(lái)講就是:
1.系統(tǒng)類防止內(nèi)存中出現(xiàn)多份相同的字節(jié)碼。
2.保證Java程序安全穩(wěn)定運(yùn)行。
加載類的三種方式
到這里,相信大家都對(duì)類加載器和類的加載都有一定的了解了,那么你知道嘛?常見的加載類的方式有三種。
- 靜態(tài)加載:也就是使用
new
關(guān)鍵字來(lái)創(chuàng)建實(shí)例對(duì)象, - 動(dòng)態(tài)加載:使用
Class.forName()
動(dòng)態(tài)加載(反射加載類型),然后調(diào)用類的newInstance()
方法實(shí)例化對(duì)象。 - 動(dòng)態(tài)加載:通過(guò)類加載器的
loadClass()
方法來(lái)加載類,然后調(diào)用類的newInstance()
方法實(shí)例化對(duì)象。
三種方式的區(qū)別
- 第一種和第二種方式使用的類加載器是相同的,都是當(dāng)前類加載器(this.getClass().getClassLoader()),第三種方式需要用戶指定類加載器。
- 如果需要在當(dāng)前類路徑以外加載類,則只能使用第三種方式,
第三種方式加載的類與當(dāng)前類分屬不同的命名空間。
- 第一種方式是靜態(tài)加載,第二種和第三種是動(dòng)態(tài)加載。
兩種異常(Exception)
- 靜態(tài)加載的時(shí)候如果在運(yùn)行環(huán)境中找不到要初始化的類,拋出的是
NoClassDefFoundError
。它在Java的異常體系中是一個(gè)error
。 - 動(dòng)態(tài)加載的時(shí)候如果運(yùn)行環(huán)境中找不到要初始化的類,拋出的是
ClassNotFoundException
。它在Java的異常體系中是一個(gè)checked
異常。
Class.forName與ClassLoader.loadClass的區(qū)別
首先,我們必須要明白類加載機(jī)制的三個(gè)主要過(guò)程是:加載–>連接–>初始化。
-
Class.forName():
除了將類的.class
文件加載到JVM中之外,還對(duì)類進(jìn)行解釋,執(zhí)行類中的static塊。 - ClassLoder.loadClass():只是將類的.class文件加載到JVM中,并不會(huì)執(zhí)行類的static塊,只有在newInstance時(shí)才會(huì)執(zhí)行static塊。
-
Class.forName(name, initialize, loader)
:帶參函數(shù)也可控制是否加載static塊。并且只有調(diào)用了newInstance()方法采用調(diào)用構(gòu)造函數(shù)。創(chuàng)建類的對(duì)象 。
下面我們寫下代碼,加深一下影響。
public class Demo {
static {
System.out.println("正在加載Demo...");
}
}
import java.lang.Class;
public class TestDemo {
public static void main(String[] args) throws ClassNotFoundException {
//1.使用 Class.forName()加載類,默認(rèn)執(zhí)行static塊。
Class.forName("Demo");
//獲得當(dāng)前類的類加載器
ClassLoader classLoader = Test.class.getClassLoader();
//2.使用 Class.forName()加載類,并指定ClassLoader。初始化時(shí)不會(huì)執(zhí)行static塊。
Class.forName("Demo", false, classLoader);
//3.使用ClassLoader類的loadClass()方法加載類,不會(huì)執(zhí)行初始化
classLoader.loadClass("Demo");
}
}
只有第一行代碼輸出了
知識(shí)來(lái)源:
【基礎(chǔ)】雙親委派模型_嗶哩嗶哩_bilibili文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-673241.html
深入理解Java類加載器(ClassLoader)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-673241.html
到了這里,關(guān)于java八股文面試[JVM]——雙親委派模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!