更新時(shí)間:2022-07-18 12:44:31 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽2867次
Java 類(lèi)加載器是Java 運(yùn)行時(shí)環(huán)境的一部分,它可以將 Java 類(lèi)動(dòng)態(tài)加載到Java 虛擬機(jī)中。由于類(lèi)加載器,Java 運(yùn)行時(shí)系統(tǒng)不需要了解文件和文件系統(tǒng)。
Java 類(lèi)不會(huì)一次全部加載到內(nèi)存中,而是在應(yīng)用程序需要時(shí)加載。此時(shí),JRE調(diào)用Java ClassLoader,這些 ClassLoader 將類(lèi)動(dòng)態(tài)加載到內(nèi)存中。
并非所有類(lèi)都由單個(gè) ClassLoader 加載。根據(jù)類(lèi)的類(lèi)型和類(lèi)的路徑,決定加載該特定類(lèi)的 ClassLoader。要了解加載類(lèi)的 ClassLoader,請(qǐng)使用getClassLoader()方法。所有類(lèi)都根據(jù)它們的名稱(chēng)加載,如果找不到這些類(lèi)中的任何一個(gè),則返回NoClassDefFoundError或ClassNotFoundException。
Java 類(lèi)加載器分為三種類(lèi)型:
BootStrap ClassLoader:Bootstrap ClassLoader是一個(gè)機(jī)器代碼,它在 JVM 調(diào)用它時(shí)啟動(dòng)操作。它不是一個(gè)java類(lèi)。它的工作是加載第一個(gè)純Java ClassLoader。Bootstrap ClassLoader 從rt.jar位置加載類(lèi)。Bootstrap ClassLoader 沒(méi)有任何父 ClassLoader。它也被稱(chēng)為Primodial ClassLoader。
Extension ClassLoader: Extension ClassLoader 是 Bootstrap ClassLoader 的子類(lèi),從各自的 JDK Extension 庫(kù)中加載核心 java 類(lèi)的擴(kuò)展。它從jre/lib/ext目錄或系統(tǒng)屬性java.ext.dirs指向的任何其他目錄加載文件。
系統(tǒng)類(lèi)加載器:應(yīng)用程序類(lèi)加載器也稱(chēng)為系統(tǒng)類(lèi)加載器。它加載在環(huán)境變量CLASSPATH、-classpath 或 -cp 命令行選項(xiàng)中找到的應(yīng)用程序類(lèi)型類(lèi)。Application ClassLoader 是 Extension ClassLoader 的子類(lèi)。
注意:ClassLoader 委托層次模型總是按照 Application ClassLoader->Extension ClassLoader->Bootstrap ClassLoader 的順序運(yùn)行。Bootstrap ClassLoader 總是被賦予更高的優(yōu)先級(jí),其次是 Extension ClassLoader,然后是 Application ClassLoader。

功能原則是Java 類(lèi)加載器工作的一組規(guī)則或特性。功能的三個(gè)原則,它們是:
委托模型:Java 虛擬機(jī)和 Java 類(lèi)加載器使用一種稱(chēng)為委托層次算法的算法將類(lèi)加載到 Java 文件中。
ClassLoader 基于委托模型給出的一組操作工作。他們是:
ClassLoader 始終遵循委托層次原則。
每當(dāng) JVM 遇到一個(gè)類(lèi)時(shí),它都會(huì)檢查該類(lèi)是否已經(jīng)加載。
如果該類(lèi)已經(jīng)加載到方法區(qū)域中,則 JVM 繼續(xù)執(zhí)行。
如果該類(lèi)不在方法區(qū)域中,則 JVM 要求 Java ClassLoader Sub-System 加載該特定類(lèi),然后 ClassLoader 子系統(tǒng)將控制權(quán)移交給Application ClassLoader。
然后,Application ClassLoader 將請(qǐng)求委托給 Extension ClassLoader,而Extension ClassLoader又將請(qǐng)求委托給Bootstrap ClassLoader。
Bootstrap ClassLoader 將在 Bootstrap 類(lèi)路徑(JDK/JRE/LIB)中搜索。如果類(lèi)可用,則加載它,否則將請(qǐng)求委托給 Extension ClassLoader。
Extension ClassLoader 在 Extension Classpath(JDK/JRE/LIB/EXT) 中搜索類(lèi)。如果類(lèi)可用,則加載它,否則將請(qǐng)求委托給 Application ClassLoader。
Application ClassLoader 在 Application Classpath 中搜索類(lèi)。如果該類(lèi)可用,則加載它,如果不可用,則生成ClassNotFoundException異常。

可見(jiàn)性原則:可見(jiàn)性原則指出,由父類(lèi)加載器加載的類(lèi)對(duì)子類(lèi)加載器可見(jiàn),但由子類(lèi)加載器加載的類(lèi)對(duì)父類(lèi)加載器不可見(jiàn)。假設(shè)一個(gè)類(lèi) GEEKS.class 已被 Extension ClassLoader 加載,那么該類(lèi)僅對(duì) Extension ClassLoader 和 Application ClassLoader 可見(jiàn),而對(duì) Bootstrap ClassLoader 不可見(jiàn)。如果再次嘗試使用 Bootstrap ClassLoader 加載該類(lèi),則會(huì)給出異常java.lang.ClassNotFoundException。
唯一性屬性:唯一性屬性確保類(lèi)是唯一的并且沒(méi)有類(lèi)的重復(fù)。這也確保了父類(lèi)加載器加載的類(lèi)不會(huì)被子類(lèi)加載器加載。如果父類(lèi)加載器無(wú)法找到該類(lèi),那么只有當(dāng)前實(shí)例會(huì)嘗試自己這樣做。
在 JVM 請(qǐng)求類(lèi)之后,需要執(zhí)行幾個(gè)步驟來(lái)加載類(lèi)。類(lèi)是根據(jù)委托模型加載的,但有一些重要的方法或函數(shù)在加載類(lèi)中起著至關(guān)重要的作用。
loadClass(String name, boolean resolve):該方法用于加載JVM引用的類(lèi)。它將類(lèi)的名稱(chēng)作為參數(shù)。這是 loadClass(String, boolean) 類(lèi)型。
defineClass():defineClass() 方法是最終方法,不能被覆蓋。此方法用于將字節(jié)數(shù)組定義為類(lèi)的實(shí)例。如果類(lèi)無(wú)效,則拋出ClassFormatError。
findClass(String name):此方法用于查找指定的類(lèi)。此方法只查找但不加載類(lèi)。
findLoadedClass(String name):該方法用于驗(yàn)證 JVM 引用的 Class 之前是否已加載。
Class.forName(String name, boolean initialize, ClassLoader loader):該方法用于加載類(lèi)以及初始化類(lèi)。此方法還提供了選擇任何一個(gè) ClassLoader 的選項(xiàng)。如果 ClassLoader 參數(shù)為 NULL,則使用 Bootstrap ClassLoader。
示例:在加載類(lèi)之前執(zhí)行以下代碼:
protected synchronized Class<?>
loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = findLoadedClass(name);
try {
if (c == NULL) {
if (parent != NULL) {
c = parent.loadClass(name, false);
}
else {
c = findBootstrapClass0(name);
}
}
catch (ClassNotFoundException e)
{
System.out.println(e);
}
}
}
注意:如果一個(gè)類(lèi)已經(jīng)被加載,它會(huì)返回它。否則,它將對(duì)新類(lèi)的搜索委托給父類(lèi)加載器。如果父類(lèi)加載器沒(méi)有找到該類(lèi),loadClass()調(diào)用方法findClass()來(lái)查找并加載該類(lèi)。如果父ClassLoader沒(méi)有找到該類(lèi), findClass()方法會(huì)在當(dāng)前ClassLoader中搜索該類(lèi)。如果大家想了解更多相關(guān)知識(shí),不妨來(lái)關(guān)注一下動(dòng)力節(jié)點(diǎn)的Java在線學(xué)習(xí),里面的課程內(nèi)容從入門(mén)到精通,很適合零基礎(chǔ)的小伙伴學(xué)習(xí),希望對(duì)大家能夠有所幫助。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話(huà)與您溝通安排學(xué)習(xí)