Java類加載器--默認的三種類加載器(AppClassLoader/ExtClassLoader/BootstrapClassLoader)

一 什么是ClassLoader

大家都知道敲才,當我們寫好一個Java程序之后务荆,不是管是CS還是BS應用虑乖,都是由若干個.class文件組織而成的一個完整的Java應用程序,當程序在運行時闯团,即會調用該程序的一個入口函數(shù)來調用系統(tǒng)的相關功能密任,而這些功能都被封裝在不同的class文件當中,所以經(jīng)常要從這個class文件中要調用另外一個class文件中的方法偷俭,如果另外一個文件不存在的,則會引發(fā)系統(tǒng)異常缰盏。而程序在啟動的時候涌萤,并不會一次性加載程序所要用的所有class文件,而是根據(jù)程序的需要口猜,通過Java的類加載機制(ClassLoader)來動態(tài)加載某個class文件到內存當中的负溪,從而只有class文件被載入到了內存之后,才能被其它class所引用济炎。所以ClassLoader就是用來動態(tài)加載class文件到內存當中用的川抡。

其中具體加載過程為:JVM加載.class字節(jié)碼到內存,而.class文件時怎么被加載到JVM中的就是Java ClassLoader需要做的事情.

JVM什么時候加載.class文件

  1. 當執(zhí)行new操作時候
  2. 當執(zhí)行Class.forName(“包路徑 + 類名”)\ Class.forName(“包路徑 + 類名”, ClassLoader)\ ClassLoader.loadClass(“包路徑 + 類名”)

以上情況都會觸發(fā)類加載器去類加載對應的路徑去查找對應的.class文件,并創(chuàng)建Class對象.

不過第((2))方式加載字節(jié)碼到內存后生產(chǎn)的只是一個Class對象,要得到具體的對象實例還需要使用Class對象的newInstance()方法來創(chuàng)建具體實例.

再引用一段話來說明什么是類加載器:

虛擬機設計團隊把類加載階段中的“通過一個類的全限定名來獲取描述此類的二進制字節(jié)流”這個動作放到Java虛擬機外部去實現(xiàn),以便讓應用程序自己決定如何去獲取所需要的類。實現(xiàn)這個動作的代碼模塊稱為“類加載器”崖堤。

類加載器可以說是Java語言的一項創(chuàng)新侍咱,也是Java語言流行的重要原因之一,它最初是為了滿足Java Applet的需求而開發(fā)出來的密幔。雖然目前Java Applet技術基本上已經(jīng)“死掉”楔脯,但類加載器卻在類層次劃分、OSGi胯甩、熱部署昧廷、代碼加密等領域大放異彩,成為了Java技術體系中一塊重要的基石偎箫,可謂是失之桑榆木柬,收之東隅。

類加載器雖然只用于實現(xiàn)類的加載動作淹办,但它在Java程序中起到的作用卻遠遠不限于類加載階段眉枕。對于任意一個類,都需要由加載它的類加載器和這個類本身一同確立其在Java虛擬機中的唯一性娇唯,每一個類齐遵,都擁有一個獨立的類名稱空間。這句話可以表達得更通俗一些:比較兩個類是否“相等”塔插,只有在這兩個類是由同一個類加載器加載的前提下才有意義梗摇。否則,即使這兩個類來源于同一個Class文件想许,被同一個虛擬機加載伶授,只要加載它們的類加載器不同,那這兩個類就必定不相等流纹。

二 AppClassLoader

AppClassLoader應用類加載器,又稱為系統(tǒng)類加載器,負責在JVM啟動時,加載來自在命令java中的classpath或者java.class.path系統(tǒng)屬性或者CLASSPATH操作系統(tǒng)屬性所指定的JAR類包和類路徑.

public class AppClassLoaderTest {

    public static void main(String[] args) {
        System.out.println(ClassLoader.getSystemClassLoader());
    }

}

輸出結果如下:

sun.misc.Launcher$AppClassLoader@73d16e93

以上結論說明調用ClassLoader.getSystemClassLoader()可以獲得AppClassLoader類加載器.

protected ClassLoader() {
    this(checkCreateClassLoader(), getSystemClassLoader());
}

通過查看ClassLoader的源碼發(fā)現(xiàn)并且在沒有特定說明的情況下,用戶自定義的任何類加載器都將該類加載器作為自定義類加載器的父加載器.

String classPath = System.getProperty("java.class.path");
for (String path : classPath.split(";")) {
    System.out.println(path);
}

通過執(zhí)行上面的代碼即可獲得classpath的加載路徑.

在上面的main函數(shù)的類的加載就是使用AppClassLoader加載器進行加載的,可以通過執(zhí)行下面的代碼得出這個結論

public class AppClassLoaderTest {

    public static void main(String[] args) {
        ClassLoader classLoader = Test.class.getClassLoader();
        System.out.println(classLoader);
        System.out.println(classLoader.getParent());
    }

    private static class Test {

    }

}

執(zhí)行結果如下:

sun.misc.Launcher$AppClassLoader@73d16e93
sun.misc.Launcher$ExtClassLoader@15db9742

從上面的運行結果可以得知AppClassLoader的父加載器是ExtClassLoader,接下來繼續(xù)說一下ExtClassLoader類加載器.

三 ExtClassLoader

ExtClassLoader稱為擴展類加載器糜烹,主要負責加載Java的擴展類庫,默認加載JAVA_HOME/jre/lib/ext/目錄下的所有jar包或者由java.ext.dirs系統(tǒng)屬性指定的jar包.放入這個目錄下的jar包對AppClassLoader加載器都是可見的(因為ExtClassLoader是AppClassLoader的父加載器,并且Java類加載器采用了委托機制).

ExtClassLoader的類掃描路徑通過執(zhí)行下面代碼來看一下:

String extDirs = System.getProperty("java.ext.dirs");
for (String path : extDirs.split(";")) {
System.out.println(path);
}

執(zhí)行結果如下:

C:\Java\jdk1.8.0_101\jre\lib\ext
C:\Windows\Sun\Java\lib\ext

其中C:\Java\jdk1.8.0_101\jre\lib\ext路徑下內容為:
這里寫圖片描述
從上面的路徑中隨意選擇一個類,來看看他的類加載器是什么:

ClassLoader classLoader = sun.security.ec.SunEC.class.getClassLoader();
System.out.println(classLoader);
System.out.println(classLoader.getParent());

執(zhí)行結果如下:

sun.misc.Launcher$ExtClassLoader@6bc7c054
null

從上面的程序運行結果可知ExtClassLoader的父加載器為null.

四 BootstrapClassLoader

稱為啟動類加載器,是Java類加載層次中最頂層的類加載器漱凝,負責加載JDK中的核心類庫疮蹦,如:rt.jar、resources.jar茸炒、charsets.jar等愕乎,可通過如下程序獲得該類加載器從哪些地方加載了相關的jar或class文件:

URL[] urLs = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL url : urLs) {
    System.out.println(url.toExternalForm());
}

程序執(zhí)行結果如下:

file:/C:/Java/jdk1.8.0_101/jre/lib/resources.jar
file:/C:/Java/jdk1.8.0_101/jre/lib/rt.jar
file:/C:/Java/jdk1.8.0_101/jre/lib/sunrsasign.jar
file:/C:/Java/jdk1.8.0_101/jre/lib/jsse.jar
file:/C:/Java/jdk1.8.0_101/jre/lib/jce.jar
file:/C:/Java/jdk1.8.0_101/jre/lib/charsets.jar
file:/C:/Java/jdk1.8.0_101/jre/lib/jfr.jar
file:/C:/Java/jdk1.8.0_101/jre/classes

從rt.jar中選擇String類,看一下String類的類加載器是什么

ClassLoader classLoader = String.class.getClassLoader();
System.out.println(classLoader);

執(zhí)行結果如下:

null

可知由于BootstrapClassLoader對Java不可見,所以返回了null,我們也可以通過某一個類的加載器是否為null來作為判斷該類是不是使用BootstrapClassLoader進行加載的依據(jù).另外上面提到ExtClassLoader的父加載器返回的是null,那是否說明ExtClassLoader的父加載器是BootstrapClassLoader?

Bootstrap ClassLoader是由C/C++編寫的,它本身是虛擬機的一部分壁公,所以它并不是一個JAVA類感论,也就是無法在java代碼中獲取它的引用,JVM啟動時通過Bootstrap類加載器加載rt.jar等核心jar包中的class文件紊册,之前的int.class,String.class都是由它加載比肄。然后呢,我們前面已經(jīng)分析了,JVM初始化sun.misc.Launcher并創(chuàng)建Extension ClassLoader和AppClassLoader實例芳绩。并將ExtClassLoader設置為AppClassLoader的父加載器掀亥。Bootstrap沒有父加載器,但是它卻可以作用一個ClassLoader的父加載器示括。比如ExtClassLoader铺浇。這也可以解釋之前通過ExtClassLoader的getParent方法獲取為Null的現(xiàn)象

尊重原創(chuàng)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市垛膝,隨后出現(xiàn)的幾起案子鳍侣,更是在濱河造成了極大的恐慌,老刑警劉巖吼拥,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倚聚,死亡現(xiàn)場離奇詭異,居然都是意外死亡凿可,警方通過查閱死者的電腦和手機惑折,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枯跑,“玉大人惨驶,你說我怎么就攤上這事×仓” “怎么了粗卜?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纳击。 經(jīng)常有香客問我续扔,道長,這世上最難降的妖魔是什么焕数? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任纱昧,我火速辦了婚禮,結果婚禮上堡赔,老公的妹妹穿的比我還像新娘识脆。我一直安慰自己,他們只是感情好善已,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布灼捂。 她就那樣靜靜地躺著,像睡著了一般雕拼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粘招,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天啥寇,我揣著相機與錄音,去河邊找鬼。 笑死辑甜,一個胖子當著我的面吹牛衰絮,可吹牛的內容都是我干的。 我是一名探鬼主播磷醋,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼猫牡,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了邓线?” 一聲冷哼從身側響起淌友,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骇陈,沒想到半個月后震庭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡你雌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年器联,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婿崭。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡拨拓,死狀恐怖,靈堂內的尸體忽然破棺而出氓栈,到底是詐尸還是另有隱情渣磷,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布颤绕,位于F島的核電站幸海,受9級特大地震影響,放射性物質發(fā)生泄漏奥务。R本人自食惡果不足惜物独,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望氯葬。 院中可真熱鬧挡篓,春花似錦、人聲如沸帚称。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闯睹。三九已至戏羽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間楼吃,已是汗流浹背始花。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工妄讯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人酷宵。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓亥贸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親浇垦。 傳聞我的和親對象是個殘疾皇子炕置,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355