類加載機(jī)制

一:雙親委派機(jī)制
ClassLoader#loadClass(ClassLoader源碼

二:類加載器
普通的類只需要有1、2、3加載器就夠了殿如,有特殊需求需要4莺治、5。
注:JVM調(diào)用BootstrapClassLoader啟動(dòng),然后BootstrapClassLoader構(gòu)造ExtClassLoader并啟動(dòng)它,加載擴(kuò)展類,構(gòu)造AppClassLoader公你,等到需要加載類路徑下的某類到內(nèi)存中才生效。即:JVM啟動(dòng)假瞬,BootstrapClassLoader和ExtClassLoader就會(huì)生效陕靠,AppClassLoader會(huì)等有類加載需求再生效,以上的加載都是自動(dòng)加載脱茉,不需要程序員去調(diào)loadClass()進(jìn)行加載剪芥。

1:BootStrapClassLoader
啟動(dòng)類加載器:加載的類庫(kù)位置是"C:\Program Files\Java\jdk1.8.0_151\jre\lib"。
1.1:c++編寫芦劣,已嵌入到了JVM內(nèi)核當(dāng)中粗俱。
1.2:如何通過(guò)Java的類加載器獲取到,ExtClassLoader的getParent()獲取到的是null(在類加載器部分:null就是指BootstrapClassLoader)虚吟。

/**
* 1:BootstrapClassLoader加載的類庫(kù)
* System.getProperty("sun.boot.class.path”)
*
* 結(jié)果:
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\sunrsasign.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;
* C:\Program Files\Java\jdk1.8.0_151\jre\classes
*/
System.out.println(System.getProperty("sun.boot.class.path"));

2:ExtClassLoader
擴(kuò)展類加載器:加載的類庫(kù)位置是"C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext".
2.1:java編寫寸认,位于sun.misc包下,該包在你導(dǎo)入源代碼的時(shí)候是沒(méi)有的串慰,需要重新去下偏塞,該包是openjdk的包,不公開(kāi)源代碼邦鲫。

/**
* 1:ExtClassLoader加載的類庫(kù)
* System.getProperty("java.ext.dirs")
*
* 結(jié)果:
* C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext;
* C:\Windows\Sun\Java\lib\ext
*/
System.out.println(System.getProperty("java.ext.dirs"));

3:AppClassLoader
應(yīng)用程序類加載器:加載classpath下的class.
1:java編寫灸叼,位于sun.misc包下神汹,該包是openjdk的包,不公開(kāi)源代碼古今。

System.getProperty("java.class.path")的結(jié)果值就是AppClassLoader加載的類庫(kù)屁魏。
比較好的理解就是:idea上自己編寫的普通類就是AppClassLoader加載的。

4:CustomerClassLoader
自定義類加載器:自定義類加載器一般都是extends ClassLoader捉腥,然后重寫其findClass()方法氓拼,不要去重寫loadClass()方法,即不要去破壞其雙親委派的機(jī)制抵碟。

自定義類加載器的使用場(chǎng)景:
1:加密:Java代碼可以輕易的被反編譯桃漾,如果你需要把自己的代碼進(jìn)行加密以防止反編譯,可以先將編譯后的代碼用某種加密算法加密拟逮,類加密后就不能再用Java的ClassLoader去加載類了撬统,這時(shí)就需要自定義ClassLoader在加載類的時(shí)候先解密類,然后再加載敦迄。
2:從非標(biāo)準(zhǔn)的來(lái)源加載代碼:如果你的字節(jié)碼是放在數(shù)據(jù)庫(kù)恋追、甚至是在云端,就可以自定義類加載器颅崩,從指定的來(lái)源加載類几于。
1蕊苗、2的綜合運(yùn)用:比如你的應(yīng)用需要通過(guò)網(wǎng)絡(luò)來(lái)傳輸Java類的字節(jié)碼沿后,為了安全性,這些字節(jié)碼經(jīng)過(guò)了加密處理朽砰,這個(gè)時(shí)候你就需要自定義類加載器來(lái)從某個(gè)網(wǎng)絡(luò)地址上讀取加密后的字節(jié)代碼(findClass())尖滚,接著進(jìn)行解密和驗(yàn)證,最后定義(defineClass())出在Java虛擬機(jī)中運(yùn)行的類瞧柔。

5:ThreadContextClassLoader
線程上下文類加載器(TCCL):每一個(gè)線程都有一個(gè)關(guān)聯(lián)的ThreadContextClassLoader漆弄。

引入TCCL的原因:
    Jvm的類加載機(jī)制是雙親委派機(jī)制,從父類加載器開(kāi)始加載再子類加載器加載造锅。若針對(duì)spi的接口和實(shí)現(xiàn)撼唾,spi的接口是核心類庫(kù),是由BootStrapClassLoader加載的哥蔚,BootStrapClassLoader是加載不到第三方j(luò)ar中的spi實(shí)現(xiàn)類的倒谷,因此引入線程上下文加載器,反向打通雙親委派糙箍,讓BootStrapClassLoader可以指定線程上下文加載器來(lái)加載spi的實(shí)現(xiàn)類渤愁。
注:線程上下文加載器若不設(shè)置,則默認(rèn)是AppClassLoader(該默認(rèn)的類加載器是Jvm設(shè)置的)深夯。

TCCL的作用:
1:解決委派雙親加載模式的缺點(diǎn)抖格。
2:實(shí)現(xiàn)了jndi,spi接口的加載。

TCCL的使用場(chǎng)景:
1:當(dāng)高層提供了統(tǒng)一接口讓低層去實(shí)現(xiàn)雹拄,同時(shí)又要是在高層加載(或?qū)嵗┑蛯拥念悤r(shí)收奔,必須通過(guò)線程上下文類加載器來(lái)幫助高層的ClassLoader找到并加載該類。參考:[https://blog.csdn.net/yangcheng33/article/details/52631940](https://blog.csdn.net/yangcheng33/article/details/52631940)
2:當(dāng)使用本類托管類加載滓玖,然而加載本類的ClassLoader未知時(shí)筹淫,為了隔離不同的調(diào)用者,可以取調(diào)用者各自的線程上下文類加載器代為托管呢撞。 
Thread和TCCL的關(guān)系
new Thread()將繼承父線程的TCCL损姜。如果程序?qū)CCL沒(méi)有任何改動(dòng),則程序的所有線程將都使用AppClassLoader作為TCCL殊霞。
設(shè)置TCCL的方式:Thread.currentThread().setContextClassLoader("類加載器")
注:TCCL是線程隔離的摧阅,每個(gè)線程可以有不同的TCCL。 
個(gè)人認(rèn)為绷蹲,TCCL可以和自定義類加載器一起使用棒卷,設(shè)置某一類線程的類加載器為自定義類加載器,專門做一些處理祝钢。 
/**
* <p>
*  TCCL
* </p>
* @author: zhu.chen
* @date: 2020/8/3
* @version: v1.0.0
*/
public class Test {
    public static void main(String[] args) {
        /**
         * 1:JVM會(huì)為每個(gè)線程設(shè)置默認(rèn)TCCL為AppClassLoader
         * 子線程t線程會(huì)繼承main的TCCL也為AppClassLoader
         */
        // main:sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println(Thread.currentThread().getContextClassLoader());
        Thread t = new Thread(() -> System.out.println("xxx"));
        t.start();
        // t:sun.misc.Launcher$AppClassLoader@18b4aac2
        System.out.println(t.getContextClassLoader());
        /**
         * 2:主線程設(shè)置了TCCL為Test1
         * 子線程t1繼承main的TCCL也為Test1(main和t的TCCL是一樣的)
         */
        Thread.currentThread().setContextClassLoader(new Test1());
        // com.example.demo2.Test$Test1@79fc0f2f
        System.out.println(Thread.currentThread().getContextClassLoader());
        Thread t1 = new Thread(() -> System.out.println("xxx"));
        t1.start();
        // com.example.demo2.Test$Test1@79fc0f2f
        System.out.println(t1.getContextClassLoader());
    }
    /**
     * 自定義類加載器
     */
    public static class Test1 extends ClassLoader {
    }
}

三:Java虛擬機(jī)是如何判定兩個(gè)Java類是相同的比规?
Java虛擬機(jī)不僅要看類的全名是否相同,還要看加載此類的類加載器是否一樣拦英,只有兩者都相同的情況蜒什,才認(rèn)為兩個(gè)類是相同的,即便是同樣的字節(jié)代碼疤估,被不同的類加載器加載之后所得到的類灾常,也是不同的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铃拇,一起剝皮案震驚了整個(gè)濱河市钞瀑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慷荔,老刑警劉巖雕什,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異显晶,居然都是意外死亡贷岸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門吧碾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凰盔,“玉大人,你說(shuō)我怎么就攤上這事倦春』Ь矗” “怎么了落剪?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)尿庐。 經(jīng)常有香客問(wèn)我忠怖,道長(zhǎng),這世上最難降的妖魔是什么抄瑟? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任凡泣,我火速辦了婚禮,結(jié)果婚禮上皮假,老公的妹妹穿的比我還像新娘鞋拟。我一直安慰自己,他們只是感情好惹资,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布贺纲。 她就那樣靜靜地躺著,像睡著了一般褪测。 火紅的嫁衣襯著肌膚如雪猴誊。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天侮措,我揣著相機(jī)與錄音懈叹,去河邊找鬼。 笑死分扎,一個(gè)胖子當(dāng)著我的面吹牛澄成,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笆包,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼环揽,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了庵佣?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤汛兜,失蹤者是張志新(化名)和其女友劉穎巴粪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體粥谬,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肛根,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漏策。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片派哲。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖掺喻,靈堂內(nèi)的尸體忽然破棺而出芭届,到底是詐尸還是另有隱情储矩,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布褂乍,位于F島的核電站持隧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏逃片。R本人自食惡果不足惜屡拨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望褥实。 院中可真熱鬧呀狼,春花似錦、人聲如沸损离。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)草冈。三九已至她奥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怎棱,已是汗流浹背哩俭。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拳恋,地道東北人凡资。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像谬运,于是被迫代替她去往敵國(guó)和親隙赁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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