久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

快速了解類(lèi)加載采用雙親委托機(jī)制的原因與實(shí)現(xiàn)

 IT樂(lè)知 2020-05-20

Java中類(lèi)加載采用的是雙親委托機(jī)制,,為什么要這樣處理?又是怎樣實(shí)現(xiàn)的呢,?接下來(lái)簡(jiǎn)單說(shuō)說(shuō)我的理解,。

總覽圖

         首先我們要知道雙親委托機(jī)制是怎么樣的,總覽圖如下圖:

        

         Java中類(lèi)的加載器主要有2種,,Java虛擬機(jī)自帶的加載器和用戶(hù)自定義的類(lèi)加載器,,自帶加載器有3個(gè):

         根類(lèi)加載器( Bootstrap):加載JRE\lib\rt.jar或者-Xbootclasspath指定的jar包,由C++實(shí)現(xiàn),不是ClassLoader子類(lèi)。主要加載最基礎(chǔ)的啟動(dòng)類(lèi)的包,。

         擴(kuò)展類(lèi)加載器(Extension):加載JRE\lib\ext\*.jar或者-Djava.ext.dirs指定目錄下的jar包,。主要加載JDK的擴(kuò)展包。

         應(yīng)用類(lèi)加載器( System ):加載CLASSPATH或者Djava.class.path知道目錄下的類(lèi)和jar包,。加載的是我們用戶(hù)開(kāi)發(fā)的class,,比如項(xiàng)目下的。

         剩下的都是用戶(hù)自定義的類(lèi)加載器,,自定義類(lèi)加載器需要繼承java.lang.ClassLoader,,這樣用戶(hù)就可以定制類(lèi)的加載方式了!

         可以看到虛擬機(jī)自帶的3個(gè)加載器分別加載jdk基礎(chǔ)包,、jdk擴(kuò)展包,、用戶(hù)創(chuàng)建的class,所以自帶的加載器就滿(mǎn)足基本需求了,,不過(guò)有時(shí)候我們會(huì)需要加載一些特殊class或者不一樣的加載方式,,就需要自定義了!

實(shí)現(xiàn)方案

         我們都知道雙親委派,,那么他們是如何實(shí)現(xiàn)的呢,?

         首先我們通過(guò)一下代碼:

         ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

         可以獲取到應(yīng)用類(lèi)加載器,跟進(jìn)源碼,,大致過(guò)程和主要代碼如下圖:

        

         ClassLoader.getSystemClassLoader()方法中調(diào)用了initSystemClassLoader(),,在這個(gè)方法中通過(guò)調(diào)用Launcher類(lèi)的loader屬性,通過(guò)靜態(tài)對(duì)象launcher找到Launcher類(lèi)的初始化方法,。最終在初始化方法中初始化了Launcher類(lèi)的內(nèi)部類(lèi)ExtClassLoader,、AppClassLoader,而這兩個(gè)初始化最終調(diào)用了ClassLoader類(lèi)的ClassLoader(Void unused, ClassLoader parent)構(gòu)造函數(shù),。

         ClassLoader(Void unused, ClassLoader parent)函數(shù)設(shè)置了加載器的“private final ClassLoader parent;”屬性,。ExtClassLoader的parent為null;AppClassLoader的parent屬性為ExtClassLoader

         在看ClassLoader最重要的方法loadClass(),,關(guān)鍵代碼如下圖:

        

         關(guān)鍵部分已經(jīng)圈出,,主要流程是:

         1、查看類(lèi)是否已經(jīng)加載

         2,、如果沒(méi)有加載,,如果parent屬性不為null就調(diào)用parent的loadClass方法,否則調(diào)用Bootstrap類(lèi)加載器加載,。

         3,、如果還是沒(méi)有加載成功,就調(diào)用當(dāng)前加載器去加載,。

         通過(guò)第1步實(shí)現(xiàn)了通過(guò)加載器從下往上查找類(lèi)是否加載,,通過(guò)第2,、3步實(shí)現(xiàn)從上往下加載類(lèi),通過(guò)這樣就實(shí)現(xiàn)了類(lèi)的雙親委托機(jī)制,!

注意:通過(guò)以上源碼我們可以看出,,類(lèi)加載器不是通過(guò)繼承實(shí)現(xiàn)委托機(jī)制,而是通過(guò)組合,!

為什么這樣實(shí)現(xiàn)?

         先看如下一段代碼,,如下圖:

        

         代碼中我自己實(shí)現(xiàn)了一個(gè)最簡(jiǎn)單的類(lèi)加載器,,他重寫(xiě)了loadClass方法,通過(guò)自定義的類(lèi)加載器創(chuàng)建了一個(gè)ClassLoadTest的實(shí)例,。通過(guò)倒數(shù)第二行的打印可以看出,,創(chuàng)建的實(shí)例并不是當(dāng)前這個(gè)類(lèi)的實(shí)例!

         看下面的代碼,,如下圖:

        

         在代碼中我想把產(chǎn)生的實(shí)例轉(zhuǎn)換成ClassLoadTest,,程序運(yùn)行報(bào)錯(cuò)。為什么會(huì)發(fā)生這種情況呢,?

         因?yàn)閛這個(gè)類(lèi)是由自定義的類(lèi)加載器加載的,,而ClassLoadTest在啟動(dòng)的時(shí)候已經(jīng)由systemClassLoader加載器加載,即這兩個(gè)類(lèi)來(lái)源于同一個(gè) Class文件,,被同一個(gè)Java虛擬機(jī)加載,,只要加載它們的類(lèi)加載器不同,那這兩個(gè)類(lèi)就必定不相等,!

         這樣設(shè)計(jì)有什么好處呢,?

         通過(guò)這樣設(shè)計(jì)Java中需要的基礎(chǔ)類(lèi)無(wú)論是被誰(shuí)加載最終都會(huì)往上傳遞由指定的類(lèi)加載器加載,保證了內(nèi)存中基礎(chǔ)類(lèi)只存在一種,,比如Object類(lèi)在程序的各種類(lèi)加載器環(huán)境中都能夠保證是同一個(gè)類(lèi),!

總結(jié)

         類(lèi)加載關(guān)系并不是像普通的層級(jí)關(guān)系通過(guò)繼承來(lái)實(shí)現(xiàn),而是通過(guò)組合實(shí)現(xiàn),,每個(gè)類(lèi)加載器都有一個(gè)parent屬性,,指明他的上級(jí)加載器,每次加載的類(lèi)的時(shí)候先調(diào)用parent去加載,,如果parent為null,,則直接調(diào)用根類(lèi)加載器,如果都沒(méi)有加載成功,,才調(diào)用當(dāng)前類(lèi)加載器加載,。舉例一個(gè)應(yīng)用類(lèi)加載過(guò)程如下圖:

        

         每個(gè)類(lèi)加載即使加載的是同一個(gè)字節(jié)碼文件,這兩個(gè)類(lèi)也不相同,,所以雙親委派就很好地解決了各個(gè)類(lèi)加載器協(xié)作時(shí)基礎(chǔ)類(lèi)型的一致性問(wèn)題(越基礎(chǔ)的類(lèi)由越上層的加載器進(jìn)行加載),。

Java程序員日常學(xué)習(xí)筆記,如理解有誤歡迎各位交流討論!

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多