ClassLoader類加載器順序Demo測試與雙親委派源碼解讀

上一篇 <<<javap命令反查匯編指令匯總
下一篇 >>>自定義SPI和熱部署技術(shù)破壞類加載器的雙親委派模式


java是邏輯程序,class是虛擬機(jī)指令程序。
類加載器:將我們class文件讀取到內(nèi)存中阅悍。

class文件的來源

  1. 自己寫的java源代碼 編譯成class文件 硬盤讀取
  2. 通過網(wǎng)絡(luò)的方式下載class文件
  3. War跳纳、Jar 解壓之后都是class文件
  4. 從數(shù)據(jù)庫中讀取class文件
  5. Java動(dòng)態(tài)代理模式 反射/cglib 生成代理class文件

類加載過程

1碟狞、加載(Loading)

a讹俊、class字節(jié)碼文件數(shù)據(jù)轉(zhuǎn)換成方法區(qū)中的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)【字節(jié)碼文件可以是本地,也可以來自于網(wǎng)絡(luò)亚情、光盤摊腋、硬盤等二進(jìn)制】
b沸版、在堆中創(chuàng)建代表類的class對象(注意不是目標(biāo)類對象,用newInstance就可以生成對象)兴蒸,作為方法區(qū)類數(shù)據(jù)的訪問入口视粮,該對象封裝了類在方法區(qū)中的數(shù)據(jù)結(jié)構(gòu),并且向用戶提供了訪問方法區(qū)數(shù)據(jù)結(jié)構(gòu)的接口橙凳,即Java反射的接口蕾殴。

2、鏈接(Linking)

1)岛啸、驗(yàn)證(Verification):確保加載的類信息符合JVM規(guī)范钓觉,沒有安全方面的問題【JVM校驗(yàn)】
a.文件格式驗(yàn)證:主要驗(yàn)證字節(jié)流是否符合Class文件格式規(guī)范,并且能被當(dāng)前的虛擬機(jī)加載處理坚踩。例如:主荡灾,次版本號是否在當(dāng)前虛擬機(jī)處理的范圍之內(nèi)。常量池中是否有不被支持的常量類型瞬铸。指向常量的中的索引值是否存在不存在的常量或不符合類型的常量卧晓。
b.元數(shù)據(jù)驗(yàn)證:對字節(jié)碼描述的信息進(jìn)行語義的分析,分析是否符合java的語言語法的規(guī)范赴捞。
c.字節(jié)碼驗(yàn)證:最重要的驗(yàn)證環(huán)節(jié),分析數(shù)據(jù)流和控制郁稍,確定語義是合法的赦政,符合邏輯的。主要的針對元數(shù)據(jù)驗(yàn)證后對方法體的驗(yàn)證。保證類方法在運(yùn)行時(shí)不會(huì)有危害出現(xiàn)恢着。
d.符號引用驗(yàn)證:主要是針對符號引用轉(zhuǎn)換為直接引用的時(shí)候桐愉,是會(huì)延伸到第三解析階段,主要去確定訪問類型等涉及到引用的情況掰派,主要是要保證引用一定會(huì)被訪問到从诲,不會(huì)出現(xiàn)類等無法訪問的問題。

2)靡羡、準(zhǔn)備(Preparation):正式為類變量(static變量)分配內(nèi)存并設(shè)置類變量初始值的階段系洛,這些內(nèi)存都將在方法區(qū)中進(jìn)行分配【空間分配】
3)、解析(Resolution):虛擬機(jī)常量池的符號引用替換為字節(jié)引用過程【靜態(tài)和常量池引用替換】

3略步、初始化(Initialization)

初始化階段是執(zhí)行類構(gòu)造器<clinit>()方法的過程描扯。

  • 在多線程環(huán)境中會(huì)被正確加鎖和同步
  • 自動(dòng)收集類中變量的復(fù)制動(dòng)作,以及static塊的語句合并產(chǎn)生趟薄,static從上往下執(zhí)行绽诚,如果父類未初始化,則先初始化父類杭煎。

雙親委派層次結(jié)構(gòu)

a恩够、啟動(dòng)(Bootstrap)類加載器【加載JVM自身的類,由C++實(shí)現(xiàn)羡铲,沒有父類蜂桶,文件名寫死】
Bootstrap啟動(dòng)類加載器只加載包名為java、javax犀勒、sun等開頭的類屎飘,位于<JAVA_HOME>/lib路徑下的核心類庫和-Xbootclasspath參數(shù)指定的路徑下的jar包

/**
 * 啟動(dòng)類加載器的職責(zé)(注意最后的classes目錄沒有的話自己創(chuàng)建)
 * /Home/jre/lib/resources.jar
 * /Home/jre/lib/rt.jar
 * /Home/jre/lib/sunrsasign.jar
 * /Home/jre/lib/jsse.jar
 * /Home/jre/lib/jce.jar
 * /Home/jre/lib/charsets.jar
 * /Home/jre/lib/jfr.jar
 * /Home/jre/classes
 */
public static void bootstrapClassLoader() {
    String property = System.getProperty("sun.boot.class.path");
    List<String> list = Arrays.asList(property.split(";"));
    list.forEach((t) -> {
        System.out.println("啟動(dòng)類加載器目錄:" + t);
    });
}

b、擴(kuò)展(ExtClassLoader)類加載器【由Java語言實(shí)現(xiàn)贾费,父類加載器為null】
由Java語言實(shí)現(xiàn)的钦购,是Launcher的靜態(tài)內(nèi)部類,它負(fù)責(zé)加載<JAVA_HOME>/lib/ext目錄下或者由系統(tǒng)變量-Djava.ext.dir指定位路徑中的類庫褂萧,開發(fā)者可以直接使用標(biāo)準(zhǔn)擴(kuò)展類加載器押桃。

/**
 * 擴(kuò)展類加載器
 * /Home/jre/lib/ext
 * /Library/Java/Extensions
 * /Network/Library/Java/Extensions
 * /System/Library/Java/Extensions
 * /usr/lib/java
 */
public static void extClassLoader() {
    String property = System.getProperty("java.ext.dirs");
    List<String> list = Arrays.asList(property.split(";"));
    list.forEach((t) -> {
        System.out.println("擴(kuò)展類加載器" + t);
    });
}

c、系統(tǒng) (AppClassLoader) 類加載器【由Java語言實(shí)現(xiàn)导犹,父類加載器為ExtClassLoader】
也稱應(yīng)用程序加載器是指唱凯,它負(fù)責(zé)加載classpath路徑,該類加載是程序中默認(rèn)的類加載器谎痢,通過ClassLoader#getSystemClassLoader()方法可以獲取到該類加載器磕昼。

/**
 * app 類加載器(除了包含啟動(dòng)類和擴(kuò)展類,還包括自己寫的代碼)
 * /target/classes
 */
public static void appClassLoader() {
    String property = System.getProperty("java.class.path");
    List<String> list = Arrays.asList(property.split(";"));
    list.forEach((t) -> {
        System.out.println("應(yīng)用類加載器" + t);
    });
}

d节猿、自定義類加載器票从,父類加載器肯定為AppClassLoader漫雕。

雙親委派模式原理及好處

原理:
如果一個(gè)類加載器收到了類加載請求,它并不會(huì)自己先去加載峰鄙,而是把這個(gè)請求委托給父類的加載器去執(zhí)行(存在遞歸)浸间,倘若父類加載器無法完成此加載任務(wù),子加載器才會(huì)嘗試自己去加載吟榴,這就是雙親委派模式魁蒜。

好處:
a、避免類的重復(fù)加載吩翻,當(dāng)父親已經(jīng)加載了該類時(shí)兜看,就沒有必要子ClassLoader再加載一次。
b仿野、可以防止核心API庫被隨意篡改铣减,比如java.lang是核心API包,擴(kuò)展時(shí)強(qiáng)制加載將會(huì)報(bào)出如下異常:java.lang.SecurityException: Prohibited package name: java.lang

類加載器的觸發(fā)節(jié)點(diǎn)

1.調(diào)用類的靜態(tài)方法
2.invokeStatic 調(diào)用靜態(tài)方法
3.Main
4.New
5.Class.formname
6.子類初始化一定會(huì)初始化父類
初始化一個(gè)類脚作,一定會(huì)觸發(fā)類加載器
類加載器加載了該類葫哗,但該類不一定完成初始化。

類加載器效果測試

// 當(dāng)前classLoader【正城蛱危】:sun.misc.Launcher$AppClassLoader@18b4aac2
System.out.println(JaryeEntity.class.getClassLoader());
// 擴(kuò)展classloader:sun.misc.Launcher$ExtClassLoader@5f8ed237
System.out.println(JaryeEntity.class.getClassLoader().getParent());
// 啟動(dòng)classLoader:null(因?yàn)榈讓邮荂語言寫的)
System.out.println(JaryeEntity.class.getClassLoader().getParent().getParent());
// 把class文件放到啟動(dòng)類的/Home/jre/classes目錄下劣针,則打印結(jié)果為null
System.out.println(JaryeEntity.class.getClassLoader());
// Object在lang包下,屬于啟動(dòng)類加載亿扁,結(jié)果為null
Object o = new Object();
System.out.println(o.getClass().getClassLoader());

雙親委派源碼解讀

ClassLoader.getSystemClassLoader().loadClass("com.mysql.jdbc.Driver")

類加載器核心方法

a捺典、loadClass(String)
ClassLoader類自己實(shí)現(xiàn)的,不再建議用戶重寫但用戶可以直接調(diào)用該方法
加載時(shí)從緩存中獲取从祝,沒有則委派給啟動(dòng)類加載襟己,如果仍然未找到,則調(diào)用findClass()方法去加載牍陌。
運(yùn)行時(shí)加載自己指定的類擎浴,那么我們可以直接使用this.getClass().getClassLoder.loadClass("className"),這樣就可以直接調(diào)用ClassLoader的loadClass方法獲取到class對象毒涧。

b贮预、findClass(String)
JDK1.2之后建議把自定義的類加載邏輯寫在findClass()方法中,在loadClass()方法中被調(diào)用的契讲,這樣就可以保證自定義的類加載器符合雙親委托模式
ClassLoader類中并沒有實(shí)現(xiàn)findClass()方法的具體代碼邏輯仿吞,取而代之的是拋出ClassNotFoundException異常
findClass方法通常是和defineClass方法一起使用的

c、defineClass(byte[] b, int off, int len)
defineClass()方法是用來將byte字節(jié)流解析成JVM能夠識別的Class對象(ClassLoader中已實(shí)現(xiàn)該方法邏輯)
在自定義類加載器時(shí)捡偏,會(huì)直接覆蓋ClassLoader的findClass()方法并編寫加載規(guī)則唤冈,取得要加載類的字節(jié)碼后轉(zhuǎn)換成流,然后調(diào)用defineClass()方法生成類的Class對象

d银伟、resolveClass(Class??? c)
使用該方法可以使用類的Class對象創(chuàng)建完成也同時(shí)被解析你虹。
前面我們說鏈接階段主要是對字節(jié)碼進(jìn)行驗(yàn)證凉当,為類變量分配內(nèi)存并設(shè)置初始值同時(shí)將字節(jié)碼文件中的符號引用轉(zhuǎn)換為直接引用。


相關(guān)文章鏈接:
<<<JVM整體內(nèi)存結(jié)構(gòu)的圖解售葡,直觀明了
<<<javap命令查看對象信息及操作方法在JVM層的實(shí)現(xiàn)原理
<<<javap命令反查匯編指令匯總
<<<自定義SPI和熱部署技術(shù)破壞類加載器的雙親委派模式
<<<JVM中對象如何完成空間分配和初始化工作
<<<JVM元空間(方法區(qū))和棧內(nèi)存溢出原因及解決方案
<<<JVM堆內(nèi)存溢出和內(nèi)存泄露問題定位和解決
<<<JVM常見死鎖問題產(chǎn)生原因和多種診斷方式
<<<服務(wù)器CPU飆升為100%問題排查及如何避免
<<<JVM內(nèi)存診斷命令和排查工具匯總
<<<JVM新生代老年代算法匯總圖解
<<<JVM垃圾回收不要手動(dòng)System.gc的真正原因
<<<JVM垃圾回收引用計(jì)數(shù)法和根搜索算法圖解
<<<JVM垃圾回收STW(Stop-The-World)代碼演示
<<<JVM垃圾回收器的發(fā)展歷程及使用場景匯總
<<<JVM串行并行垃圾回收器的關(guān)注點(diǎn)
<<<一張圖看懂CMS垃圾回收器的底層原理
<<<G1能作為JDK9默認(rèn)垃圾回收器的優(yōu)勢分析
<<<CMS和G1的漏標(biāo)問題解決及三色標(biāo)記算法圖解
<<<GC中新生代進(jìn)入老年代的方式匯總
<<<GC常用日志參數(shù)配置及分析工具說明
<<<FullGC、MinorGC忠藤、STW等常見問題如何解答
<<<JVM性能調(diào)優(yōu)的評估指標(biāo)及調(diào)優(yōu)示例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挟伙,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子模孩,更是在濱河造成了極大的恐慌尖阔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榨咐,死亡現(xiàn)場離奇詭異介却,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)块茁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門齿坷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人数焊,你說我怎么就攤上這事永淌。” “怎么了佩耳?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵遂蛀,是天一觀的道長。 經(jīng)常有香客問我干厚,道長李滴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任蛮瞄,我火速辦了婚禮所坯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘裕坊。我一直安慰自己包竹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布籍凝。 她就那樣靜靜地躺著周瞎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饵蒂。 梳的紋絲不亂的頭發(fā)上声诸,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機(jī)與錄音退盯,去河邊找鬼彼乌。 笑死泻肯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的慰照。 我是一名探鬼主播灶挟,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毒租!你這毒婦竟也來了稚铣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤墅垮,失蹤者是張志新(化名)和其女友劉穎惕医,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體算色,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抬伺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灾梦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峡钓。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖斥废,靈堂內(nèi)的尸體忽然破棺而出椒楣,到底是詐尸還是另有隱情,我是刑警寧澤牡肉,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布捧灰,位于F島的核電站,受9級特大地震影響统锤,放射性物質(zhì)發(fā)生泄漏毛俏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一饲窿、第九天 我趴在偏房一處隱蔽的房頂上張望煌寇。 院中可真熱鬧,春花似錦逾雄、人聲如沸阀溶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽银锻。三九已至,卻和暖如春做鹰,著一層夾襖步出監(jiān)牢的瞬間击纬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工钾麸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留更振,地道東北人炕桨。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像肯腕,于是被迫代替她去往敵國和親献宫。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

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