日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java类二次加载_深入理解java之类加载器

發(fā)布時(shí)間:2025/3/20 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java类二次加载_深入理解java之类加载器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、類與類加載器

類加載器:實(shí)現(xiàn)加載階段的第一步,通過(guò)一個(gè)類的全限定名來(lái)將這個(gè)類的二進(jìn)制字節(jié)流加載進(jìn)jvm。

類與類加載器:任意一個(gè)類唯一性都是由它本身和加載它的類加載器確定,兩個(gè)類是否相等在它們是由同一個(gè)類加載器加載的前提下。

jvm虛擬機(jī)中包括兩種類加載器:一種是啟動(dòng)類加載器(Bootstrap ClassLoader),它是使用C++實(shí)現(xiàn);另一種是其他所有用java實(shí)現(xiàn)的類加載器。

從java程序角度:

1)啟動(dòng)類加載器:負(fù)責(zé)加載\lib目錄下或者被-Xbootclasspath參數(shù)所指定的路徑中的類,此外要求文件名被虛擬機(jī)識(shí)別,如果不被jvm識(shí)別也無(wú)法被加載。

2)擴(kuò)展類加載器:負(fù)責(zé)加載\lib\exit目錄下或者被java.exit.dirs系統(tǒng)變量所指定的路徑中的所有類庫(kù)。

3)應(yīng)用程序類加載器(系統(tǒng)類加載器):它是Classloader中的getSystemClassloader()方法的返回值。負(fù)責(zé)加載用戶類路徑上所指定的類庫(kù),如果應(yīng)用程序中沒(méi)有自定義類加載器,這個(gè)就為程序中默認(rèn)的類加載器。

免費(fèi)在線視頻教學(xué):java視頻教程

二、雙親委派模型

除了頂層的啟動(dòng)類加載器,其余所有類加載器都有自己的父類加載器。父子關(guān)系不以繼承實(shí)現(xiàn),而是以組合關(guān)系來(lái)復(fù)用父類加載器。

工作過(guò)程: 類加載器接到類加載請(qǐng)求–>將請(qǐng)求委派給父類加載器(直到最頂層啟動(dòng)類加載器)–>父類嘗試加載,加載失敗反饋給子類加載器–>子類加載器嘗試加載

雙親委派模型的好處:保證java底層API的穩(wěn)定,避免加載和基本類重名(Object)的自定義類導(dǎo)致出現(xiàn)多個(gè)不同的重名的類(Object),從而造成java基礎(chǔ)行為的混亂。

雙親委派模型源碼:

方法加同步鎖保證線程安全,首先檢查該類是否被加載過(guò),如果沒(méi)有加載則調(diào)用父類加載器的loadClass()方法,若父類加載器為空說(shuō)明是啟動(dòng)類加載器,則調(diào)用啟動(dòng)類加載器。

如果父類加載失敗會(huì)拋出ClassNotFoundException,在調(diào)用自己的findClass()方法進(jìn)行加載。protected Class> loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

//同步鎖

synchronized (getClassLoadingLock(name)) {

// 首先檢車這個(gè)類是不是已被加載

Class> c = findLoadedClass(name);

if (c == null) {

long t0 = System.nanoTime();

try {

if (parent != null) {

//如果父類不為空則調(diào)用父類加載器的loadClass方法

c = parent.loadClass(name, false);

} else {

//沒(méi)有父類則默認(rèn)調(diào)用啟動(dòng)類加載器加載

c = findBootstrapClassOrNull(name);

}

} catch (ClassNotFoundException e) {

//如果父類加載器找不到這個(gè)類則拋出ClassNotFoundException

}

if (c == null) {

// 父類加載器失敗時(shí)調(diào)用自身的findClass方法加載

long t1 = System.nanoTime();

c = findClass(name);

//記錄

sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);

sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);

sun.misc.PerfCounter.getFindClasses().increment();

}

}

if (resolve) {

resolveClass(c);

}

return c;

}

}

三、破壞雙親委派模型

1.第一次破壞

雙親委派模型出現(xiàn)在JDK1.2之后,而類加載器和抽象類java.lang.ClassLoader已經(jīng)存在。

因此為了向前兼容,JDK1.2之后在ClassLoader中添加了一個(gè)新的protected方法findClass。用戶把自己的類加載邏輯寫(xiě)在findClass方法中,而不是重寫(xiě)loadClass方法,從而保證自定義的類加載符合雙親委派模型。

2.第二次破壞

模型自身有缺陷。雙親委派可以確保各個(gè)類加載器的基礎(chǔ)類的統(tǒng)一,這是在用戶代碼調(diào)用基礎(chǔ)類的情況下,如果出現(xiàn)基礎(chǔ)類回調(diào)用戶代碼那就不適用了。比如涉及到SPI的場(chǎng)景去加載所需要的SPI代碼。

SPI機(jī)制的介紹參考其他文章。

為了解決這個(gè)問(wèn)題,引入了線程上下文加載器(Thread Context ClassLoader),這個(gè)類加載器就可以通過(guò)java.lang.Thread類中的setContextClassLoader()方法進(jìn)行設(shè)置,如果創(chuàng)建線程時(shí)未設(shè)置將會(huì)從父線程中繼承一個(gè),如果全局都沒(méi)有則默認(rèn)就是應(yīng)用程序類加載器,利用這個(gè)加載器可以完成父類加載器請(qǐng)求子類加載器加載的動(dòng)作。

3.第三次破壞

由于對(duì)程序動(dòng)態(tài)性追求導(dǎo)致,如熱部署,熱替換等。

比如模塊化標(biāo)準(zhǔn)OSGi R4.2中將雙親委派的樹(shù)形結(jié)構(gòu)變成了更復(fù)雜的網(wǎng)狀結(jié)構(gòu)。

java文章教程推薦:java入門(mén)教程

總結(jié)

以上是生活随笔為你收集整理的java类二次加载_深入理解java之类加载器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。