Jvm類加載器

參考鏈接:https://blog.csdn.net/briblue/article/details/54973413

三大類加載器與各自加載的包,執(zhí)行順行

Bootstrap ClassLoader 最頂層的加載類,主要加載核心類庫募舟,%JRE_HOME%\lib下的rt.jar部蛇、resources.jar辽聊、charsets.jar和class等靡砌。另外需要注意的是可以通過啟動jvm時指定-Xbootclasspath和路徑來改變Bootstrap ClassLoader的加載目錄扩然。比如java -Xbootclasspath/a:path被指定的文件追加到默認的bootstrap路徑中觅闽。我們可以打開我的電腦帝雇,在上面的目錄下查看,看看這些jar包是不是存在于這個目錄蛉拙。

Extention ClassLoader 擴展的類加載器尸闸,加載目錄%JRE_HOME%\lib\ext目錄下的jar包和class文件。還可以加載-D java.ext.dirs選項指定的目錄孕锄。

Appclass Loader 也稱為SystemAppClass 加載當前應用的classpath的所有類

加載順序:

1. Bootstrap CLassloder

2. Extention ClassLoader

3. AppClassLoader

測試Bootstrap CLassloder 加載的東西

System.out.println(System.getProperty("sun.boot.class.path"));

結果:

C:\Program Files\Java\jre1.8.0_91\lib\resources.jar;

C:\Program Files\Java\jre1.8.0_91\lib\rt.jar;

C:\Program Files\Java\jre1.8.0_91\lib\sunrsasign.jar;

C:\Program Files\Java\jre1.8.0_91\lib\jsse.jar;

C:\Program Files\Java\jre1.8.0_91\lib\jce.jar;

C:\Program Files\Java\jre1.8.0_91\lib\charsets.jar;

C:\Program Files\Java\jre1.8.0_91\lib\jfr.jar;

C:\Program Files\Java\jre1.8.0_91\classes

測試Extention ClassLoader 加載的東西

System.out.println(System.getProperty("java.ext.dirs"));

結果:

C:\Program Files\Java\jre1.8.0_91\lib\ext;C:\Windows\Sun\Java\lib\ext

測試AppClassLoader 加載的東西

System.out.println(System.getProperty("java.class.path"));

結果:

D:\workspace\ClassLoaderDemo\bin

這個路徑其實就是當前java工程目錄bin吮廉,里面存放的是編譯生成的class文件,java工程中的bin目錄一般存放的都是編譯.java文件生成的二進制.class可執(zhí)行文件

查看類記載器

執(zhí)行代碼:

public class Hello {

public static void main(String[] args) {

  ClassLoader cl = Hello.class.getClassLoader();

    System.out.println("ClassLoader is:"+cl.toString());

   }
 }

結果:

 ClassLoader is:jdk.internal.loader.ClassLoaders$[AppClassLoader@4f8e5cde](mailto:AppClassLoader@4f8e5cde)

也就是說明Hello.class文件是由AppClassLoader加載的畸肆,而像int.class宦芦,string.class是由Bootstrap ClassLoader加載的

每個類加載器都有一個父加載器(父加載器不是父類)

查看AppClassLoader的父加載器,執(zhí)行代碼:

   public static void main(String[] args) {

   ClassLoader cl = Hello.class.getClassLoader();

   System.out.println("ClassLoader\'s parent is:"+cl.getParent().toString());

  }

結果:

ClassLoader's parent is:jdk.internal.loader.ClassLoaders$[PlatformClassLoader@311d617d](mailto:PlatformClassLoader@311d617d)

這個說明恼除,AppClassLoader的父加載器是ExtClassLoader踪旷,ExtClassLoader的parent是null

類圖比較

image.png

Bootstrap ClassLoader是由C++編寫的曼氛。

Bootstrap ClassLoader是由C++編寫的。

Bootstrap ClassLoader是由C/C++編寫的令野,它本身是虛擬機的一部分舀患,所以它并不是一個JAVA類,也就是無法在java代碼中獲取它的引用气破,JVM啟動時通過Bootstrap類加載器加載rt.jar等核心jar包中的class文件聊浅,之前的int.class,String.class都是由它加載。然后呢现使,我們前面已經分析了低匙,JVM初始化sun.misc.Launcher并創(chuàng)建Extension ClassLoader和AppClassLoader實例。并將ExtClassLoader設置為AppClassLoader的父加載器碳锈。Bootstrap沒有父加載器顽冶,但是它卻可以作用一個ClassLoader的父加載器。比如ExtClassLoader售碳。這也可以解釋之前通過ExtClassLoader的getParent方法獲取為Null的現(xiàn)象

雙親委托查找

一個類加載器查找class和resource時强重,是通過“委托模式”進行的,它首先判斷這個class是不是已經加載成功贸人,如果沒有的話它并不是自己進行查找间景,而是先通過父加載器,然后遞歸下去艺智,直到Bootstrap ClassLoader倘要,如果Bootstrap classloader找到了,直接返回十拣,如果沒有找到封拧,則一級一級返回,最后到達自身去查找這些對象父晶。這種機制就叫做雙親委托

image.png

用序列描述一下:

1. 一個AppClassLoader查找資源時捂龄,先看看緩存是否有逸吵,緩存有從緩存中獲取稿黄,否則委托給父加載器愧旦。

2. 遞歸,重復第1部的操作埠胖。

3. 如果ExtClassLoader也沒有加載過糠溜,則由Bootstrap ClassLoader出面,它首先查找緩存直撤,如果沒有找到的話非竿,就去找自己的規(guī)定的路徑下,也就是sun.mic.boot.class下面的路徑谋竖。找到就返回红柱,沒有找到承匣,讓子加載器自己去找。

4. Bootstrap ClassLoader如果沒有查找成功锤悄,則ExtClassLoader自己在java.ext.dirs路徑中去查找韧骗,查找成功就返回,查找不成功零聚,再向下讓子加載器找袍暴。

5. ExtClassLoader查找不成功,AppClassLoader就自己查找隶症,在java.class.path路徑下查找政模。找到就返回。如果沒有找到就讓子類找蚂会,如果沒有子類會怎么樣淋样?拋出各種異常

重要方法loadClass()

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException

1. 執(zhí)行findLoadedClass(String)去檢測這個class是不是已經加載過了。

2. 執(zhí)行父加載器的loadClass方法胁住。如果父加載器為null习蓬,則jvm內置的加載器去替代,也就是Bootstrap ClassLoader措嵌。這也解釋了ExtClassLoader的parent為null,但仍然說Bootstrap ClassLoader是它的父加載器。

3. 如果向上委托父加載器沒有加載成功芦缰,則通過findClass(String)查找企巢,前面說過ExtClassLoader的parent為null,所以它向上委托時让蕾,系統(tǒng)會為它指定Bootstrap ClassLoader

要注意的是如果要編寫一個classLoader的子類浪规,也就是自定義一個classloader,建議覆蓋findClass()方法探孝,而不要直接改寫loadClass()方法

例如:

 if (parent != null) {

  //父加載器不為空則調用父加載器的loadClass

   c = parent.loadClass(name, false);

   } else {

   //父加載器為空則調用Bootstrap Classloader

   c = findBootstrapClassOrNull(name);

}

自定義ClassLoader

不知道大家有沒有發(fā)現(xiàn)笋婿,不管是Bootstrap ClassLoader還是ExtClassLoader等,這些類加載器都只是加載指定的目錄下的jar包或者資源顿颅。如果在某種情況下缸濒,我們需要動態(tài)加載一些東西呢?比如從D盤某個文件夾加載一個class文件粱腻,或者從網絡上下載class主內容然后再進行加載庇配,這樣可以嗎?如果要這樣做的話绍些,需要我們自定義一個classloader

自定義步驟

1.編寫一個類繼承自ClassLoader抽象類捞慌。

2.復寫它的findClass()方法。

3.在findClass()方法中調用defineClass(), 這個方法在編寫自定義classloader的時候非常重要柬批,它能將class . 二進制內容轉換成Class對象啸澡,如果不符合要求的會拋出各種異常

注意:一個ClassLoader創(chuàng)建時如果沒有指定parent袖订,那么它的parent默認就是AppClassLoader

可根據鏈接:https://blog.csdn.net/briblue/article/details/54973413查看自定義ClassLoad的例子

關鍵字 路徑

類加載器的關聯(lián)部分就是路徑,也就是要加載的class或者是資源的路徑嗅虏。

BootStrap ClassLoader洛姑、ExtClassLoader、AppClassLoader都是加載指定路徑下的jar包旋恼。如果我們要突破這種限制吏口,實現(xiàn)自己某些特殊的需求,我們就得自定義ClassLoader冰更,自已指定加載的路徑产徊,可以是磁盤、內存蜀细、網絡或者其它

常見的用法是將Class文件按照某種加密手段進行加密舟铜,然后按照規(guī)則編寫自定義的ClassLoader進行解密,這樣我們就可以在程序中加載特定了類奠衔,并且這個類只能被我們自定義的加載器進行加載谆刨,提高了程序的安全性

可根據鏈接:https://blog.csdn.net/briblue/article/details/54973413查看例子

每個Thread都有一個相關聯(lián)的ClassLoader,默認是AppClassLoader归斤。并且子線程默認使用父線程的ClassLoader除非子線程特別設置

總結

ClassLoader用來加載class文件的痊夭。

系統(tǒng)內置的ClassLoader通過雙親委托來加載指定路徑下的class和資源。

可以自定義ClassLoader一般覆蓋findClass()方法脏里。

ContextClassLoader與線程相關她我,可以獲取和設置,可以繞過雙親委托的機制

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末迫横,一起剝皮案震驚了整個濱河市番舆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矾踱,老刑警劉巖恨狈,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異呛讲,居然都是意外死亡禾怠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門贝搁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刃宵,“玉大人,你說我怎么就攤上這事徘公∩ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵关面,是天一觀的道長坦袍。 經常有香客問我十厢,道長,這世上最難降的妖魔是什么捂齐? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任蛮放,我火速辦了婚禮,結果婚禮上奠宜,老公的妹妹穿的比我還像新娘包颁。我一直安慰自己,他們只是感情好压真,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布娩嚼。 她就那樣靜靜地躺著,像睡著了一般滴肿。 火紅的嫁衣襯著肌膚如雪岳悟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天泼差,我揣著相機與錄音贵少,去河邊找鬼。 笑死堆缘,一個胖子當著我的面吹牛滔灶,可吹牛的內容都是我干的。 我是一名探鬼主播吼肥,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼宽气,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潜沦?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绪氛,失蹤者是張志新(化名)和其女友劉穎唆鸡,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體枣察,經...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡争占,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了序目。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臂痕。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖猿涨,靈堂內的尸體忽然破棺而出握童,到底是詐尸還是另有隱情,我是刑警寧澤叛赚,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布澡绩,位于F島的核電站稽揭,受9級特大地震影響肥卡,放射性物質發(fā)生泄漏溪掀。R本人自食惡果不足惜步鉴,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望氛琢。 院中可真熱鬧喊递,春花似錦艺沼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挽荡。三九已至藐石,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間定拟,已是汗流浹背于微。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留青自,地道東北人株依。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像延窜,于是被迫代替她去往敵國和親恋腕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容