類加載器

在jvm中的類基本上都是由類加載器來加載的(像基本數(shù)據(jù)類型疫诽,數(shù)組類型這些不是類加載器加載的,是由jvm自己加載的)胯努。并且對(duì)于java中的一個(gè)類是由加載它的類加載器和這個(gè)類本身所 唯一確定的贪磺。也就是說如果兩個(gè)類是來源同一個(gè)Class文件但沒有被同一個(gè)類加載器加載拧略,那么這兩個(gè)類就不是相等的。
這里面說的“相等”李破,是類的Class對(duì)象的equals()方法宠哄、isAssignableForm()方法、isInstance()方法返回的結(jié)果嗤攻,也包括使用instanceof這個(gè)關(guān)鍵字所判定的情況毛嫉。

雙親委派模型

從使用Java的程序員來說,Java提供的類加載器可以分為這3種:

  • 啟動(dòng)類加載器(Bootstrap ClassLoader):這個(gè)類加載器在HotSpot虛擬機(jī)中是由C++實(shí)現(xiàn)的妇菱。主要負(fù)責(zé)將<JAVA_HOME>\lib 目錄下的承粤,或者是-Xbootclasspath參數(shù)所指定的路徑中的,并且是虛擬機(jī)按照文件名識(shí)別的恶耽,也就是說只會(huì)識(shí)別虛擬機(jī)事先定義好的幾個(gè)包密任,你把第三方或者是自己打的jar包放再目錄下也不會(huì)被這個(gè)類加載器加載。
    用Class.getClassLoader()方法來獲取類的加載器的時(shí)候偷俭,如果這個(gè)類是Bootstrap ClassLoader加載的那么則會(huì)返回null浪讳。
    代碼如下:
/**
     * Returns the class loader for the class.  Some implementations may use
     * null to represent the bootstrap class loader. This method will return
     * null in such implementations if this class was loaded by the bootstrap
     * class loader.
     *
     */
@CallerSensitive
    public ClassLoader getClassLoader() {
        ClassLoader cl = getClassLoader0();
        if (cl == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
        }
        return cl;
    }
  • 擴(kuò)展類加載器(Extension ClassLoader):這個(gè)類加載器是sun.misc.Launcher$ExtClassLoader來試下的,它負(fù)責(zé)加載<JAVA_HOME>\lib\ext目錄下類庫(kù)涌萤。我們可以直接在代碼中使用這個(gè)類加載器淹遵。
  • 應(yīng)用程序類加載器(Application ClassLoader):這個(gè)類加載器是sun.misc.Launcher$AppClassLoader實(shí)現(xiàn)的口猜。這個(gè)類加載器是ClassLoader類中的getSystemClassLoader()方法返回的。所以我們一般稱之為類加載器透揣。它負(fù)責(zé)加載用戶類路徑(就是ClassPath)上所指定的目錄济炎。我們可以直接使用這個(gè)類加載器,如果我們沒有自定義類加載器一般情況下我們可以使用這個(gè)加載器辐真。

我們也可以自己定義類加載器须尚,這些類加載器的關(guān)系如下圖:

上圖所示的這種層次關(guān)系我們一般稱之為雙親委派模型(Parents Delegation Model)。雙親委派模型要求除了頂層的啟動(dòng)類加載器之外侍咱,其他的類加載都應(yīng)當(dāng)有自己的父類加載器耐床。這里類加載器之間的父子關(guān)系一般不會(huì)以繼承的方式實(shí)現(xiàn),而是使用組合的方式復(fù)用父類加載器的代碼楔脯。

雙親委派模式的工作過程:

如果一個(gè)類加載收到了類加載的請(qǐng)求撩轰,它不會(huì)自己去嘗試加載這個(gè)類,而是把這個(gè)請(qǐng)求委派給父類加載器去完成昧廷,每個(gè)層次都是這樣堪嫂,因此所欲的加載請(qǐng)求在這個(gè)模式下都會(huì)傳送到頂層的啟動(dòng)類加載器中去。只有當(dāng)父加載器加載不了這個(gè)類的時(shí)候子類加載器才會(huì)去嘗試加載木柬。

雖然這種雙親委派模型雖然是Java推薦的一種實(shí)現(xiàn)方式皆串,但是它不是強(qiáng)制的。也就是說我們可以自己定義一個(gè)加載器不用去把它交給父加載器弄诲。

使用這種雙親委派模型來進(jìn)行類加載有什么好處呢愚战?首先,它讓類加載器具有了一種帶有優(yōu)先級(jí)的層次關(guān)系齐遵。比如類java.lang.Object,它存放在rt.jar中寂玲,但是無論哪一個(gè)類加載器要加載這個(gè)類,最終都會(huì)到啟動(dòng)類加載器上進(jìn)行加載梗摇,所以O(shè)bject類在這種雙親委派模型下都是同一個(gè)類拓哟。如果沒有使用這個(gè)模型,那么我們自己編寫了一個(gè)java.lang.Object伶授,并放在程序的ClassPath中断序,那系統(tǒng)中將會(huì)出現(xiàn)多個(gè)不同的Object類,那么程序就會(huì)很很亂糜烹,正確性也無法得到保證违诗。

那如何實(shí)現(xiàn)這個(gè)雙親委派模型呢?其實(shí)java里實(shí)現(xiàn)是非常簡(jiǎn)單的疮蹦。我們只需要繼承ClassLoader后诸迟,重新findClass方法即可。具體的ClassLoader里的loadClass()方法如下:

    /**
     * Loads the class with the specified <a href="#name">binary name</a>.  The
     * default implementation of this method searches for classes in the
     * following order:
     *
     * @param  name
     *         The <a href="#name">binary name</a> of the class
     *
     * @param  resolve
     *         If <tt>true</tt> then resolve the class
     *
     * @return  The resulting <tt>Class</tt> object
     *
     * @throws  ClassNotFoundException
     *          If the class could not be found
     */
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 首先,檢查請(qǐng)求的類是否已經(jīng)被加載過了
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // 說明父類無法加載
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // 調(diào)用本身的findClass去加載
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阵苇,一起剝皮案震驚了整個(gè)濱河市壁公,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绅项,老刑警劉巖紊册,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異快耿,居然都是意外死亡囊陡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門润努,熙熙樓的掌柜王于貴愁眉苦臉地迎上來关斜,“玉大人示括,你說我怎么就攤上這事铺浇。” “怎么了垛膝?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵鳍侣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我吼拥,道長(zhǎng)倚聚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任凿可,我火速辦了婚禮惑折,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枯跑。我一直安慰自己惨驶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布敛助。 她就那樣靜靜地躺著粗卜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纳击。 梳的紋絲不亂的頭發(fā)上续扔,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音焕数,去河邊找鬼纱昧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛堡赔,可吹牛的內(nèi)容都是我干的识脆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼存璃!你這毒婦竟也來了仑荐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤纵东,失蹤者是張志新(化名)和其女友劉穎粘招,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偎球,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洒扎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了衰絮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袍冷。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖猫牡,靈堂內(nèi)的尸體忽然破棺而出胡诗,到底是詐尸還是另有隱情,我是刑警寧澤淌友,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布煌恢,位于F島的核電站,受9級(jí)特大地震影響震庭,放射性物質(zhì)發(fā)生泄漏瑰抵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一器联、第九天 我趴在偏房一處隱蔽的房頂上張望二汛。 院中可真熱鬧,春花似錦拨拓、人聲如沸肴颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)苫昌。三九已至,卻和暖如春幸海,著一層夾襖步出監(jiān)牢的瞬間祟身,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工物独, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袜硫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓挡篓,卻偏偏與公主長(zhǎng)得像婉陷,于是被迫代替她去往敵國(guó)和親帚称。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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