【Java】深入理解Java虛擬機6——類的加載器及雙親委派

其他文章

【Java】深入理解Java虛擬機1——內(nèi)存區(qū)域以及OOM類型:http://www.reibang.com/p/65c91ba4006e
【Java】深入理解Java虛擬機2——判斷對象是否存活和引用:http://www.reibang.com/p/67c24aa93c03
【Java】深入理解Java虛擬機3——垃圾收集算法:http://www.reibang.com/p/362407886236
【Java】深入理解Java虛擬機4——內(nèi)存分配與回收策略:http://www.reibang.com/p/e21f5d5c4f42
【Java】深入理解Java虛擬機5——類的加載過程:http://www.reibang.com/p/931ef115d48e
【Java】深入理解Java虛擬機6——類的加載器及雙親委派:http://www.reibang.com/p/2f33eca93a4f

類的加載器

對于任意一個類,都需要由加載它的類加載器和這個類本身一同確立其在Java虛擬機中的唯一性变屁,每一個類加載器,都擁有一個獨立的類名稱空間慎颗。
注:比較兩個類是否“相等”,只有在這兩個類是由同一個類加載器加載的前提下才有意義,否則俯萎,即使這兩個類來源于同一個Class文件傲宜,被同一個虛擬機加載,只要加載它們的類加載器不同夫啊,那這兩個類就必定不相等函卒。這里所指的“相等”,包括代表類的Class對象的equals()方法撇眯、isAssignableFrom()方法报嵌、isInstance()方法的返回結(jié)果,也包括使用instanceof關(guān)鍵字做對象所屬關(guān)系判定等情況叛本。

    /**
     * 類加載器與instanceof關(guān)鍵字演示
     *
     * @author zzm
     */
    public class ClassLoaderTest {
        public static void main(String[] args)throws Exception {
            ClassLoader myLoader = new ClassLoader(){
            @Override
            public Class<?>loadClass(String name)throws ClassNotFoundException {
                try {
                    String fileName = name.substring(name.lastIndexOf(".")+1)+".class";
                    InputStream is = getClass().getResourceAsStream(fileName)彤钟;
                    if(is == null){
                        return super.loadClass(name)来候;
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b)逸雹;
                    return defineClass(name, b营搅,0,b.length)梆砸;
                } catch(IOException e){
                    throw new ClassNotFoundException(name)转质;
                }
            }
        };
            Object obj = myLoader.loadClass("org.fenixsoft.classloading.ClassLoaderTest").
            newInstance()帖世;
            System.out.println(obj.getClass())休蟹;
            System.out.println(obj instanceof org.fenixsoft.classloading.ClassLoaderTest);
        }
    }

運行結(jié)果:

class org.fenixsoft.classloading.ClassLoaderTest
false

根據(jù)結(jié)果分析日矫,這個對象確實是類org.fenixsoft.classloading.ClassLoaderTest實例化出來的對象赂弓,但是返回結(jié)果為false,是因為虛擬機中存在了兩個ClassLoaderTest類哪轿,一個是由系統(tǒng)應(yīng)用程序類加載器加載的盈魁,另外一個是由我們自定義的類加載器加載的,雖然都來自同一個Class文件窃诉,但依然是兩個獨立的類杨耙,做對象所屬類型檢查時結(jié)果自然為false。

雙親委派模型

從Java虛擬機的角度來講飘痛,只存在兩種不同的類加載器:一種是啟動類加載器(Bootstrap ClassLoader)珊膜,這個類加載器使用C++語言實現(xiàn)[1],是虛擬機自身的一部分宣脉;另一種就是所有其他的類加載器辅搬,這些類加載器都由Java語言實現(xiàn),獨立于虛擬機外部,并且全都繼承自抽象類java.lang.ClassLoader堪遂。

啟動類加載器(Bootstrap ClassLoader)

負責(zé)將存放在<JAVA_HOME>\lib目錄中的介蛉,或者被-Xbootclasspath參數(shù)所指定的路徑中的,并且是虛擬機識別的(僅按照文件名識別溶褪,如rt.jar币旧,名字不符合的類庫即使放在lib目錄中也不會被加載)類庫加載到虛擬機內(nèi)存中。啟動類加載器無法被Java程序直接引用猿妈,用戶在編寫自定義類加載器時吹菱,如果需要把加載請求委派給引導(dǎo)類加載器,那直接使用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.
     */
    public ClassLoader getClassLoader(){
        ClassLoader cl = getClassLoader0 ();
        if (cl == null)
            return null;
        SecurityManager sm = System . getSecurityManager ();
        if (sm鳍刷! = null){
        ClassLoader ccl = ClassLoader . getCallerClassLoader ();
        if (ccl! = null&&ccl俯抖! = cl&&输瓜!cl.isAncestor(ccl)){
        sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
    }
    }
        return cl;
    }
擴展類加載器(Extension ClassLoader)

這個加載器由sun.misc.Launcher$ExtClassLoader實現(xiàn),它負責(zé)加載<JAVA_HOME>\lib\ext目錄中的芬萍,或者被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類庫尤揣,開發(fā)者可以直接使用擴展類加載器。

應(yīng)用程序類加載器(Application ClassLoader)

這個類加載器由sun.misc.Launcher $AppClassLoader實現(xiàn)柬祠。這個類加載器是ClassLoader的getSystemClassLoader()方法的返回值北戏,所以一般也稱它為系統(tǒng)類加載器。它負責(zé)加載用戶類路徑(ClassPath)上所指定的類庫漫蛔,開發(fā)者可以直接使用這個類加載器嗜愈,如果應(yīng)用程序中沒有自定義過自己的類加載器,一般情況下這個就是程序中默認的類加載器莽龟。

雙親委派模型(Parents Delegation Model)

雙親委派模型要求除了頂層的啟動類加載器外芝硬,其余的類加載器都應(yīng)當(dāng)有自己的父類加載器。這里類加載器之間的父子關(guān)系一般不會以繼承(Inheritance)的關(guān)系來實現(xiàn)轧房,而是都使用組合(Composition)關(guān)系來復(fù)用父加載器的代碼拌阴。
注:它并不是一個強制性的約束模型,而是Java設(shè)計者推薦給開發(fā)者的一種類加載器實現(xiàn)方式奶镶。
雙親委派模型的工作過程是:如果一個類加載器收到了類加載的請求迟赃,它首先不會自己去嘗試加載這個類,而是把這個請求委派給父類加載器去完成厂镇,每一個層次的類加載器都是如此纤壁,因此所有的加載請求最終都應(yīng)該傳送到頂層的啟動類加載器中,只有當(dāng)父加載器反饋自己無法完成這個加載請求(它的搜索范圍中沒有找到所需的類)時捺信,子加載器才會嘗試自己去加載酌媒。
注:使用雙親委派模型來組織類加載器之間的關(guān)系欠痴,有一個顯而易見的好處就是Java類隨著它的類加載器一起具備了一種帶有優(yōu)先級的層次關(guān)系。例如類java.lang.Object秒咨,它存放在rt.jar之中喇辽,無論哪一個類加載器要加載這個類,最終都是委派給處于模型最頂端的啟動類加載器進行加載雨席,因此Object類在程序的各種類加載器環(huán)境中都是同一個類菩咨。相反,如果沒有使用雙親委派模型陡厘,由各個類加載器自行去加載的話抽米,如果用戶自己編寫了一個稱為java.lang.Object的類,并放在程序的ClassPath中糙置,那系統(tǒng)中將會出現(xiàn)多個不同的Object類云茸,Java類型體系中最基礎(chǔ)的行為也就無法保證,應(yīng)用程序也將會變得一片混亂谤饭。

類加載器雙親委派模型

錯誤不足之處或相關(guān)建議歡迎大家評論指出标捺,謝謝!如果覺得內(nèi)容可以的話麻煩喜歡(?)一下网持。您的支持是我最大的動力宜岛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末长踊,一起剝皮案震驚了整個濱河市功舀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌身弊,老刑警劉巖辟汰,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異阱佛,居然都是意外死亡帖汞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門凑术,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翩蘸,“玉大人,你說我怎么就攤上這事淮逊〈呤祝” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵泄鹏,是天一觀的道長郎任。 經(jīng)常有香客問我,道長备籽,這世上最難降的妖魔是什么舶治? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上霉猛,老公的妹妹穿的比我還像新娘尺锚。我一直安慰自己,他們只是感情好韩脏,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布缩麸。 她就那樣靜靜地躺著,像睡著了一般赡矢。 火紅的嫁衣襯著肌膚如雪杭朱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天吹散,我揣著相機與錄音弧械,去河邊找鬼。 笑死空民,一個胖子當(dāng)著我的面吹牛刃唐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播界轩,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼画饥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浊猾?” 一聲冷哼從身側(cè)響起抖甘,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎葫慎,沒想到半個月后衔彻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡偷办,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年艰额,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椒涯。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡柄沮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出废岂,到底是詐尸還是另有隱情祖搓,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布泪喊,位于F島的核電站棕硫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏袒啼。R本人自食惡果不足惜哈扮,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一纬纪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滑肉,春花似錦包各、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至六荒,卻和暖如春护姆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掏击。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工卵皂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砚亭。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓灯变,卻偏偏與公主長得像,于是被迫代替她去往敵國和親捅膘。 傳聞我的和親對象是個殘疾皇子添祸,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355