分析ClassLoader基本原理

類(lèi)加載

Java類(lèi)通過(guò)編譯生成對(duì)應(yīng).class文件谱姓,JVM根據(jù)實(shí)際情況把當(dāng)前需要的類(lèi)從.class動(dòng)態(tài)加載到內(nèi)存創(chuàng)建實(shí)例漂羊,ClassLoader就負(fù)責(zé)完成這個(gè)加載任務(wù)后控。有了ClassLoader匿级,Java運(yùn)行時(shí)系統(tǒng)不需要知道文件與文件系統(tǒng)的設(shè)置狂窑。

正是因?yàn)镴ava類(lèi)必須由某個(gè)類(lèi)加載器裝入到內(nèi)存媳板,我們也可以在運(yùn)行時(shí)才指定需要的類(lèi)文件。

Java中的三個(gè)默認(rèn)類(lèi)加載器

除了Bootstrap ClassLoader泉哈,每個(gè)類(lèi)裝載器都有一個(gè)父裝載器(parent class loader)蛉幸,且ExtClassLoader和AppClassLoader均繼承ClassLoader類(lèi)。

  • 引導(dǎo)(Bootstrap)類(lèi)加載器丛晦。由原生代碼(如C語(yǔ)言)編寫(xiě)奕纫,不繼承自java.lang.ClassLoader。負(fù)責(zé)加載存儲(chǔ)在<JAVA_HOME>/jre/lib目錄中的核心Java庫(kù)烫沙。

  • 擴(kuò)展(Extensions)類(lèi)加載器匹层。用來(lái)在<JAVA_HOME>/jre/lib/extjava.ext.dirs指明的目錄中加載 Java擴(kuò)展庫(kù),Java 虛擬機(jī)的實(shí)現(xiàn)會(huì)提供一個(gè)擴(kuò)展庫(kù)目錄锌蓄。該類(lèi)加載器在此目錄里面查找并加載 Java 類(lèi)升筏。該類(lèi)由sun.misc.Launcher$ExtClassLoader實(shí)現(xiàn)。

  • 應(yīng)用(Application)類(lèi)加載器瘸爽。根據(jù) Java應(yīng)用程序的類(lèi)路徑(java.class.path或CLASSPATH環(huán)境變量)來(lái)加載 Java 類(lèi)您访。一般來(lái)說(shuō),Java 應(yīng)用的類(lèi)都是由它來(lái)完成加載的剪决,可以通過(guò) ClassLoader.getSystemClassLoader()來(lái)獲取灵汪。該類(lèi)由sun.misc.Launcher$AppClassLoader實(shí)現(xiàn)

classloader

通過(guò)Bootstrap ClassLoader加載的庫(kù)

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

結(jié)果

file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/sunrsasign.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/classes

ClassLoader類(lèi)加載

ClassLoader通過(guò)雙親委托的方式來(lái)搜索類(lèi)柑潦,而雙親委托是一種委派思想享言。

當(dāng)一個(gè)ClassLoader需要加載類(lèi)的時(shí)候,這個(gè)ClassLoader會(huì)委托其父加載器去完成:首先Bootstrap ClassLoader加載器嘗試加載該類(lèi)妒茬。失敗則把工作交給ExtClassLoader担锤。ExtClassLoader失敗就把工作交給AppClassLoader蔚晨。

如果三個(gè)默認(rèn)類(lèi)加載器都加載失敗乍钻,工作只能還給發(fā)起工作的ClassLoader,由這個(gè)加載器自行選擇加載類(lèi)的文件系統(tǒng)或URL铭腕。如果所有加載器都無(wú)法加載這個(gè)類(lèi)的話银择,JVM就拋出ClassNotFoundException異常。

如果按照這個(gè)加載步驟成功累舷,類(lèi)加載器會(huì)把這個(gè)類(lèi)載入內(nèi)存浩考,初始化并返回實(shí)例。

雙親委托

使用雙親委托是為了兩個(gè)目的:運(yùn)行安全和避免重復(fù)加載被盈。

后者容易理解析孽,類(lèi)已經(jīng)被父加載器加載的話搭伤,子加載器沒(méi)有必要再次重復(fù)加載;對(duì)于前者袜瞬,有些系統(tǒng)級(jí)的類(lèi)涉及到整個(gè)JVM的運(yùn)行安全怜俐,僅能通過(guò)Bootstrap ClassLoader加載。如果不使用雙親委托邓尤,使用自定義的類(lèi)來(lái)動(dòng)態(tài)替代Java核心定義類(lèi)型拍鲤,后續(xù)系統(tǒng)將完全處于危險(xiǎn)和混亂之中。

ClassLoader層次結(jié)構(gòu)

先編寫(xiě)類(lèi)加載的代碼汞扎,其中Man是一個(gè)自行定義的普通類(lèi)

final String dir = "file:/Users/phantomVK/repositories/intelliJ/cl/src";
URLClassLoader loader = new URLClassLoader(new URL[]{new URL(dir)});
Class clazz = loader.loadClass("com.phantomvk.Man");
ClassLoader classLoader = clazz.getClassLoader();
while (classLoader != null) {
    System.out.println(classLoader);
    classLoader = classLoader.getParent();
}
System.out.println(classLoader);

加載Man的類(lèi)加載器顯示結(jié)果

sun.misc.Launcher$AppClassLoader@4b67cf4d
sun.misc.Launcher$ExtClassLoader@61bbe9ba
null

加載層次:

  • Man類(lèi)的類(lèi)加載器是AppClassLoader
  • AppClassLoader的類(lèi)加載器是ExtClassLoader
  • ExtClassLoader的類(lèi)加載器是BootstrapLoader季稳。

BootstrapLoader由C++語(yǔ)言實(shí)現(xiàn)而不是Java,不運(yùn)行在JVM管理的內(nèi)存區(qū)中澈魄。所以ExtClassLoader的類(lèi)加載器沒(méi)法顯示BootstrapLoader的引用地址景鼠,只能顯示null。

自定義ClassLoader

自定義ClassLoader比較簡(jiǎn)單

  • 只需要繼承ClassLoader父類(lèi)
  • 僅重寫(xiě)Class<?> findClass(String name)方法痹扇,指定然后返回這個(gè)類(lèi)
  • 剩余的加載過(guò)程由父類(lèi)完成莲蜘,無(wú)需手動(dòng)處理。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末帘营,一起剝皮案震驚了整個(gè)濱河市票渠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芬迄,老刑警劉巖问顷,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異禀梳,居然都是意外死亡杜窄,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)算途,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)塞耕,“玉大人,你說(shuō)我怎么就攤上這事嘴瓤∩ㄍ猓” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵廓脆,是天一觀的道長(zhǎng)筛谚。 經(jīng)常有香客問(wèn)我,道長(zhǎng)停忿,這世上最難降的妖魔是什么驾讲? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上吮铭,老公的妹妹穿的比我還像新娘时迫。我一直安慰自己,他們只是感情好谓晌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布别垮。 她就那樣靜靜地躺著,像睡著了一般扎谎。 火紅的嫁衣襯著肌膚如雪碳想。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天毁靶,我揣著相機(jī)與錄音胧奔,去河邊找鬼。 笑死预吆,一個(gè)胖子當(dāng)著我的面吹牛龙填,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拐叉,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼岩遗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了凤瘦?” 一聲冷哼從身側(cè)響起宿礁,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蔬芥,沒(méi)想到半個(gè)月后梆靖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笔诵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年返吻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乎婿。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡测僵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谢翎,到底是詐尸還是另有隱情捍靠,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布岳服,位于F島的核電站剂公,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吊宋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望璃搜。 院中可真熱鬧拖吼,春花似錦、人聲如沸这吻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)唾糯。三九已至怠硼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間移怯,已是汗流浹背香璃。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舟误,地道東北人葡秒。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像嵌溢,于是被迫代替她去往敵國(guó)和親眯牧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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

  • 0赖草、前言 讀完本文学少,你將了解到: 一、為什么說(shuō)Jabalpur語(yǔ)言是跨平臺(tái)的 二秧骑、Java虛擬機(jī)啟動(dòng)旱易、加載類(lèi)過(guò)程分...
    vivi_wong閱讀 1,232評(píng)論 0 10
  • 作者簡(jiǎn)介 原創(chuàng)微信公眾號(hào)郭霖 WeChat ID: guolin_blog 本篇是fank909的第四篇投稿阀坏,詳細(xì)...
    木木00閱讀 1,607評(píng)論 1 14
  • ClassLoader翻譯過(guò)來(lái)就是類(lèi)加載器,普通的java開(kāi)發(fā)者其實(shí)用到的不多笆檀,但對(duì)于某些框架開(kāi)發(fā)者來(lái)說(shuō)卻非常常見(jiàn)...
    時(shí)待吾閱讀 1,075評(píng)論 0 1
  • 一忌堂、什么是ClassLoader? 大家都知道,當(dāng)我們寫(xiě)好一個(gè)Java程序之后酗洒,不是管是CS還是BS應(yīng)用士修,都是由若...
    Q南南南Q閱讀 2,969評(píng)論 0 8
  • 開(kāi)心籌備春節(jié)的出行,既要照顧小朋友的需求樱衷,又要讓大人們享受到度假的放鬆棋嘲,出行攻略真是體力活
    Belenshi閱讀 57評(píng)論 0 0