做者:畢來生
微信:878799579
首先咱們來描述一個小說場景,經過這個場景在去理解咱們相關的類加載器的執行以及雙親委派模型。java
上古時代有逍遙派和萬魔宗兩個宗派,互相對立。逍遙派比萬魔門更增強勢。巔峯戰力更高。安全
有一天萬魔宗一名長老之子的僕人外出獵物期間殺掉了一小隊逍遙派歷練弟子。惋惜手腳不乾淨,留下了線索。被逍遙派探子發現了本身師弟師妹被殺。消息傳回宗門後。微信
逍遙派收到此消息後大怒,發出戰書。定要萬魔門給個交代。萬魔門宗主收到戰書後一臉莫名其妙,這麼點小事也來煩我?不知道我修煉有多重要嗎?不就是殺了幾我的麼?遂叫來大長老,「大長老你看看這戰書,這麼點事情還辦很差還要我親自來處理?要你有什麼用 ? 你去準備點東西把這件事情處理一下。退下吧!」工具
大長老灰溜溜的回去。叫來本身的兒子。上去就抽了一巴掌,看看你辦的好事。我無論了。你本身想辦法解決,解決不了就別回來了。oop
大長老之子哭喪着臉回到了本身的府邸。從本身的寶庫挑出一些珍寶前去拜訪逍遙門,看能不能經過這些珍寶解決這件事情。結果,到了逍遙派門前,守衛一看就這麼點東西就想交代。對萬魔門大長老之子說:"趕忙滾關進滾,就這麼點東西還想給咱們交代?把殺了咱們師弟師妹的人帶過來,否則這事兒不算完。「spa
大長老之子那叫一個憋屈呀,寶物什麼的他們也不要,看樣子他們是鐵了心想要哪些殺了他們的罪魁禍首。那就把他們交出去把。他們惹的事。讓他們本身解決。遂派人抓捕這些人送往逍遙派,此事才得以平息。code
下面咱們經過一張關係圖來分析一下咱們的故事場景以及對應咱們類加載器之間的關係blog
經過這個圖咱們能夠了解到咱們的小故事中與咱們Java中的類加載器的對應關係。繼承
一、宗主:引導類加載器。這個類加載使用C++語言實現的,是虛擬機自身的一部分,它負責將 <JAVA_HOME>/lib路徑下的核心類庫或-Xbootclasspath參數指定的路徑下的jar包加載到內存中,注意必因爲虛擬機是按照文件名識別加載jar包的,如rt.jar,若是文件名不被虛擬機識別,即便把jar包丟到lib目錄下也是沒有做用的(出於安全考慮,Bootstrap啓動類加載器只加載包名爲java、javax、sun等開頭的類)。遞歸
二、長老:拓展類加載器。,它負責加載<JAVA_HOME>/lib/ext目錄下或者由系統變量-Djava.ext.dir指定位路徑中的類庫,開發人員能夠直接使用標準擴展類加載器。
三、長老之子:系統類加載器。,它負責加載系統類路徑java -classpath或-D java.class.path 指定路徑下的類庫,也就是咱們常常用到的classpath路徑,開發者能夠直接使用系統類加載器,通常狀況下該類加載是程序中默認的類加載器,經過ClassLoader類中的getSystemClassLoader()方法能夠獲取到該類加載器。
四、長老之子的下人:自定義類加載器。,它須要以下步驟才能夠實現自定義效果
4.1. 繼承java.lang.ClassLoader
4.2. 重寫findClass()方法
4.3 調用defineClass()方法
一、什麼是雙親委派模型?
特定的類加載器在接到加載類的請求時,首先將加載任務委託給父類加載器,依次遞歸,若是父類加載器能夠完成類加載任務,就成功返回;只有父類加載器沒法完成此加載任務時,才本身去加載。
二、雙親委派模型是如何使用的?
1)咱們在自定義加載器中查找是否有須要加載的文件,若是已經加載過,直接返回字節碼。
對應故事場景爲:長老之子的下人本身解決不了,找到長老之子
2)若是自定義加載器沒有加載過,則詢問上一層加載器(即AppClassLoader)是否已經加載過。
對應故事場景爲:長老之子攜帶寶物前去拜訪解決此事
3) 若是沒有加載過,則詢問上一層加載器(ExtClassLoader)是否已經加載過。
對應故事場景爲:大長老解決此事
4) 若是沒有加載過,則繼續詢問上一層加載(BoopStrap ClassLoader)是否已經加載過
對應故事場景爲:宗主解決此事
5) 若是BoopStrap ClassLoader依然沒有加載過,則到本身指定類加載路徑下("sun.boot.class.path")
查看是否有對應XXX.class字節碼,有則返回,沒有則通知下一層加載器ExtClassLoader到本身指定的
類加載路徑下(java.ext.dirs)查看
6) 最後到自定義類加載器指定的路徑尚未找到對應XXX.class字節碼,則拋出異常ClassNotFoundException
一、好比兩個類A和類B都要加載Integer類:
若是不用委託而是本身加載本身的,那麼類A就會加載一份Integer字節碼,而後類B又會加載一份Integer字節碼,這樣內存中就出現了兩份Integer字節碼。
若是使用委託機制,會遞歸的向父類查找,也就是首選用Bootstrap嘗試加載,若是找不到再向下。這裏的Integer就能在Bootstrap中找到而後加載,若是此時類B也要加載Integer,也從Bootstrap開始,此時Bootstrap發現已經加載過了Integer那麼直接返回內存中的Integer而不須要從新加載,這樣內存中就只有一份Integer的字節碼了。
二、 安全性:
由於ClassLoader加載的class文件來源不少,好比編譯器編譯生成的class、其餘工具生成的字節碼。而有一些一些來源的class文件是不安全的,好比咱們自定義一個java.lang.Integer類來覆蓋jdk中默認的Integer類。裏面寫這麼一句代碼 System.exit(0);
初始化這個Integer的構造器是會退出JVM,破壞應用程序的正常進行,若是使用雙親委派機制的話該Integer類永遠不會被調用,覺得委託BootStrapClassLoader加載後會加載JDK中的Integer類而不會加載自定義的這個