java classLoader雙親委派源碼分析

一個java程序被執(zhí)行,編譯器先將.java文件編譯成class文件,然后classloader將class文件加載到j(luò)vm內(nèi)存中來執(zhí)行應(yīng)用程序瓢捉。classloader起到了至關(guān)重要的作用,下面我們來看下classloader的分類:

系統(tǒng)類加載器

  • Bootstrap ClassLoader
    用C/C++代碼實現(xiàn)的加載器,用于加載Java虛擬機運行時所需要的系統(tǒng)類弟塞,如java.lang.、java.uti.等這些系統(tǒng)類拙已,它們默認在$JAVA_HOME/jre/lib目錄中决记,也可以通過啟動Java虛擬機時指定-Xbootclasspath選項,來改變Bootstrap ClassLoader的加載目錄倍踪。
    Java虛擬機的啟動就是通過 Bootstrap ClassLoader創(chuàng)建一個初始類來完成的系宫。由于Bootstrap ClassLoader是使用C/C++語言實現(xiàn)的索昂, 所以該加載器不能被Java代碼訪問到。需要注意的是Bootstrap ClassLoader并不繼承java.lang.ClassLoader扩借。
  • Extensions ClassLoader
    用于加載 Java 的拓展類 椒惨,拓展類的jar包一般會放在$JAVA_HOME/jre/lib/ext目錄下,用來提供除了系統(tǒng)類之外的額外功能潮罪。也可以通過-Djava.ext.dirs選項添加和修改Extensions ClassLoader加載的路徑康谆。
  • App ClassLoader
    負責(zé)加載當(dāng)前應(yīng)用程序Classpath目錄下的所有jar和Class文件。也可以加載通過-Djava.class.path選項所指定的目錄下的jar和Class文件嫉到。

自定義類加載器

就是我們自己寫一個類繼承ClassLoader沃暗,然后重寫findClass方法加載指定目錄下的class文件

classLoader繼承關(guān)系

我們知道系統(tǒng)所提供的類加載器有3種類型,但是系統(tǒng)提供的ClassLoader相關(guān)類卻不只3個何恶。另外描睦,AppClassLoader的父類加載器為ExtClassLoader,并不代表AppClassLoader繼承自ExtClassLoader导而,ClassLoader的繼承關(guān)系如下所示忱叭。


image.png

可以看到上圖中共有5個ClassLoader相關(guān)類,下面簡單對它們進行介紹:

  • ClassLoader是一個抽象類今艺,其中定義了ClassLoader的主要功能韵丑。
  • SecureClassLoader繼承了抽象類ClassLoader,但SecureClassLoader并不是ClassLoader的實現(xiàn)類虚缎,而是拓展了ClassLoader類加入了權(quán)限方面的功能撵彻,加強了ClassLoader的安全性。
  • URLClassLoader繼承自SecureClassLoader实牡,用來通過URl路徑從jar文件和文件夾中加載類和資源陌僵。
  • ExtClassLoader和AppClassLoader都繼承自URLClassLoader,它們都是Launcher 的內(nèi)部類创坞,Launcher 是Java虛擬機的入口應(yīng)用碗短,ExtClassLoader和AppClassLoader都是在Launcher中進行初始化的。

雙親委派機制

類加載器查找Class所采用的是雙親委托模式题涨,所謂雙親委托模式就是首先判斷該Class是否已經(jīng)加載偎谁,如果沒有則不是自身去查找而是委托給父加載器進行查找,這樣依次的進行遞歸纲堵,直到委托到最頂層的Bootstrap ClassLoader巡雨,如果Bootstrap ClassLoader找到了該Class,就會直接返回席函,如果沒找到铐望,則繼續(xù)依次向下查找,如果還沒找到則最后會交由自身去查找。

image.png

這樣講可能會有些抽象正蛙,來直接看源碼:

    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);//第一步
            if (c == null) {
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);////第二步
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    c = findClass(name);
                }
            }
            return c;
    }

    protected final Class<?> findLoadedClass(String name) {
        ClassLoader loader;
        if (this == BootClassLoader.getInstance())
            loader = null;
        else
            loader = this;
        return VMClassLoader.findLoadedClass(loader, name);
    }
    1. findLoadedClass 在當(dāng)前classloader中查找是否加載過該class炕舵,如果沒加載過就交給父加載器進行加載
    1. parent.loadClass(name, false),父加載器存在的話就交給父加載器進行加載跟畅,不存在的就直接交由系統(tǒng)跟類加載器家在咽筋。同樣父加載器也是在當(dāng)前的classloader中查找是否加載過該class,如果沒加載過就交給父加載器進行加載徊件。不斷重復(fù)第一步奸攻,遞歸調(diào)用。
    1. 一直委托到Bootstrap ClassLoader虱痕,如果Bootstrap ClassLoader在緩存中還沒有查找到Class文件睹耐,則在自己的規(guī)定路徑$JAVA_HOME/jre/libr中或者-Xbootclasspath選項指定路徑的jar包中進行查找,如果找到則返回該Class部翘,如果沒有則交給子加載器Extensions ClassLoader硝训。
    1. Extensions ClassLoader查找$JAVA_HOME/jre/lib/ext目錄下或者-Djava.ext.dirs選項指定目錄下的jar包,如果找到就返回新思,找不到則交給App ClassLoader窖梁。
    1. App ClassLoade查找Classpath目錄下或者-Djava.class.path選項所指定的目錄下的jar包和Class文件,如果找到就返回夹囚,找不到交給我們自定義的類加載器纵刘,如果還找不到則拋出異常

兩個過程,先從下到上查詢是否有類加載器加載過該class荸哟,然后從上到下詢問類加載器是否可以加載該class

雙親委托模式的好處

采取雙親委托模式主要有兩點好處:

    1. 避免重復(fù)加載假哎,如果已經(jīng)加載過一次Class,就不需要再次加載鞍历,而是先從緩存中直接讀取舵抹。
    1. 更加安全,如果不使用雙親委托模式劣砍,就可以自定義一個String類來替代系統(tǒng)的String類惧蛹,這顯然會造成安全隱患,采用雙親委托模式會使得系統(tǒng)的String類在Java虛擬機啟動時就被加載秆剪,也就無法自定義String類來替代系統(tǒng)的String類赊淑,除非我們修改
      類加載器搜索類的默認算法。還有一點仅讽,只有兩個類名一致并且被同一個類加載器加載的類,Java虛擬機才會認為它們是同一個類钾挟,想要騙過Java虛擬機顯然不會那么容易
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洁灵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌徽千,老刑警劉巖苫费,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異双抽,居然都是意外死亡百框,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門牍汹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铐维,“玉大人,你說我怎么就攤上這事慎菲〖奚撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵露该,是天一觀的道長睬棚。 經(jīng)常有香客問我,道長解幼,這世上最難降的妖魔是什么抑党? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮撵摆,結(jié)果婚禮上新荤,老公的妹妹穿的比我還像新娘。我一直安慰自己台汇,他們只是感情好苛骨,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苟呐,像睡著了一般痒芝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上牵素,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天严衬,我揣著相機與錄音,去河邊找鬼笆呆。 笑死请琳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赠幕。 我是一名探鬼主播俄精,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼榕堰!你這毒婦竟也來了竖慧?” 一聲冷哼從身側(cè)響起嫌套,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎圾旨,沒想到半個月后踱讨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡砍的,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年痹筛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廓鞠。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡帚稠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诫惭,到底是詐尸還是另有隱情翁锡,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布夕土,位于F島的核電站馆衔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怨绣。R本人自食惡果不足惜角溃,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望篮撑。 院中可真熱鬧减细,春花似錦、人聲如沸赢笨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茧妒。三九已至萧吠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桐筏,已是汗流浹背纸型。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留梅忌,地道東北人狰腌。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像牧氮,于是被迫代替她去往敵國和親琼腔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容