classloader類(lèi)加載器_基于java類(lèi)的加載方式詳解
基礎(chǔ)概念
Classloader 類(lèi)加載器,用來(lái)加載 Java 類(lèi)到 Java 虛擬機(jī)中。與普通程序不同的是。Java程序(class文件)并不是本地的可執(zhí)行程序。當(dāng)運(yùn)行Java程序時(shí),首先運(yùn)行JVM(Java虛擬機(jī)),然后再把Java class加載到JVM里頭運(yùn)行,負(fù)責(zé)加載Java class的這部分就叫做Class Loader。
JVM本身包含了一個(gè)ClassLoader稱(chēng)為Bootstrap ClassLoader,和JVM一樣,BootstrapClassLoader是用本地代碼實(shí)現(xiàn)的,它負(fù)責(zé)加載核心JavaClass(即所有java.*開(kāi)頭的類(lèi))。另外JVM還會(huì)提供兩個(gè)ClassLoader,它們都是用Java語(yǔ)言編寫(xiě)的,由BootstrapClassLoader加載;其中Extension ClassLoader負(fù)責(zé)加載擴(kuò)展的Javaclass(例如所有javax.*開(kāi)頭的類(lèi)和存放在JRE的ext目錄下的類(lèi)),ApplicationClassLoader負(fù)責(zé)加載應(yīng)用程序自身的類(lèi)。
當(dāng)運(yùn)行一個(gè)程序的時(shí)候,JVM啟動(dòng),運(yùn)行bootstrapclassloader,該ClassLoader加載java核心API(ExtClassLoader和AppClassLoader也在此時(shí)被加載),然后調(diào)用ExtClassLoader加載擴(kuò)展API,最后AppClassLoader加載CLASSPATH目錄下定義的Class,這就是一個(gè)程序最基本的加載流程。
注: 學(xué)ClassLoader看OSGI程序應(yīng)用
什么時(shí)候JVM會(huì)使用ClassLoader加載一個(gè)類(lèi)呢?當(dāng)你使用java去執(zhí)行一個(gè)類(lèi),JVM使用ApplicationClassLoader加載這個(gè)類(lèi);然后如果類(lèi)A引用了類(lèi)B,不管是直接引用還是用Class.forName()引用,JVM就會(huì)找到加載類(lèi)A的ClassLoader,并用這個(gè)ClassLoader來(lái)加載類(lèi)B。JVM按照運(yùn)行時(shí)的有效執(zhí)行語(yǔ)句,來(lái)決定是否需要裝載新類(lèi),從而裝載盡可能少的類(lèi),這一點(diǎn)和編譯類(lèi)是不相同的。
Why use your own ClassLoader?
似乎JVM自身的ClassLoader已經(jīng)足夠了,為什么我們還需要?jiǎng)?chuàng)建自己的ClassLoader呢?
因?yàn)镴VM自帶的ClassLoader只是懂得從本地文件系統(tǒng)加載標(biāo)準(zhǔn)的java class文件,如果編寫(xiě)你自己的ClassLoader,你可以做到:
1)在執(zhí)行非置信代碼之前,自動(dòng)驗(yàn)證數(shù)字簽名
2)動(dòng)態(tài)地創(chuàng)建符合用戶(hù)特定需要的定制化構(gòu)建類(lèi)
3)從特定的場(chǎng)所取得java class,例如數(shù)據(jù)庫(kù)中
4) 等等
事實(shí)上當(dāng)使用Applet的時(shí)候,就用到了特定的ClassLoader,因?yàn)檫@時(shí)需要從網(wǎng)絡(luò)上加載java class,并且要檢查相關(guān)的安全信息。
應(yīng)用服務(wù)器大都使用了ClassLoader技術(shù),即使你不需要?jiǎng)?chuàng)建自己的ClassLoader,了解其原理也有助于更好地部署自己的應(yīng)用。
重點(diǎn)注明:其實(shí)一個(gè)已經(jīng)加載的類(lèi)是無(wú)法被更新的,如果你試圖用同一個(gè)ClassLoader再次加載同一個(gè)類(lèi),就會(huì)得到異常(java.lang.LinkageError: duplicate classdefinition),我們只能夠重新創(chuàng)建一個(gè)新的ClassLoader實(shí)例來(lái)再次加載新類(lèi)。至于原來(lái)已經(jīng)加載的類(lèi),開(kāi)發(fā)人員不必去管它,因?yàn)樗赡苓€有實(shí)例正在被使用,只要相關(guān)的實(shí)例都被內(nèi)存回收了,那么JVM就會(huì)在適當(dāng)?shù)臅r(shí)候把不會(huì)再使用的類(lèi)卸載。
絕大部分Java程序都會(huì)使用3種系統(tǒng)提供的類(lèi)加載器
1.啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader),負(fù)責(zé)將存在<JAVA_HOME>\lib目錄中的,或被-Xbootclasspath參數(shù)所指定的路徑中的,并且是虛擬機(jī)識(shí)別的類(lèi)庫(kù)加載到虛擬機(jī)里.注意是按照文件名識(shí)別,如rt.jar,名字不符合的類(lèi)庫(kù)即使放在lib目錄中也不會(huì)被加載。
2.擴(kuò)展類(lèi)加載器(ExtClassLoader),它負(fù)責(zé)<JAVA_HOME>\lib\ext目錄中的,或被java.ext.dirs系統(tǒng)變量所指定的路徑中的所有類(lèi)庫(kù).
3.應(yīng)用程序類(lèi)加載器(App-ClassLoader),通過(guò)cassLoader.getSystemClassLoader()獲取,它負(fù)責(zé)加載用戶(hù)類(lèi)路徑(ClassPath)上所指定的類(lèi)庫(kù),一般情況下這個(gè)是程序中默認(rèn)的類(lèi)加載器.
雙親委托模式 是Java設(shè)計(jì)者推薦給開(kāi)發(fā)者的一種類(lèi)加載實(shí)現(xiàn)方式.雙親委托模型的工作過(guò)程是:如果一個(gè)類(lèi)加載器收到了類(lèi)加載請(qǐng)求,它首先不會(huì)自己去嘗試加載這個(gè)類(lèi),而是把這個(gè)請(qǐng)求委派給父類(lèi)加載器去完成.每一層次的類(lèi)加載器都是如此,因此所有的加載請(qǐng)求最終都會(huì)傳送到頂層的啟動(dòng)類(lèi)加載器中,只有當(dāng)父類(lèi)加載器沒(méi)有找到所需的類(lèi)時(shí),子加載器才會(huì)嘗試自己去加載。雙親模式的好處是Java類(lèi)隨著它的類(lèi)加載器一起具備了一種帶優(yōu)先級(jí)的層次關(guān)系。例如類(lèi)Object,存放在rt.jar中,無(wú)論哪個(gè)類(lèi)加載器加載這個(gè)類(lèi),最終都是委派給處于模型最頂端的啟動(dòng)類(lèi)加載,因此Object類(lèi)在程序使用多種類(lèi)加載器環(huán)境中依然能保證是同一個(gè)類(lèi)。相反,如果沒(méi)有使用雙親模型,就可能出現(xiàn)用戶(hù)自己編寫(xiě)一個(gè)Object類(lèi),導(dǎo)致系統(tǒng)中出現(xiàn)多個(gè)不同的Object類(lèi),這樣Java類(lèi)型體系中最基礎(chǔ)的行為也就無(wú)法保證。
以上這篇classloader類(lèi)加載器_基于java類(lèi)的加載方式詳解就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java Date裝成英文String后,無(wú)法再轉(zhuǎn)回Date的解決方案
本文介紹了java Date裝成英文String后,無(wú)法再轉(zhuǎn)回Date的解決方案。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼
這篇文章主要介紹了spring中使用mybatis實(shí)現(xiàn)批量插入的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
如何解決websocket開(kāi)啟多個(gè)頁(yè)面訪問(wèn)同一個(gè)連接會(huì)失效的問(wèn)題
使用WebSocket時(shí),若多個(gè)頁(yè)面訪問(wèn)同一個(gè)WebSocket連接可能會(huì)導(dǎo)致連接失效,遇到這個(gè)問(wèn)題時(shí),可以通過(guò)在SpringBoot中使用@ServerEndpoint注解并添加@Component來(lái)解決,出現(xiàn)連接錯(cuò)誤通常是因?yàn)閃ebSocket連接接收到的是一個(gè)GET請(qǐng)求2024-09-09
詳解springboot和vue前后端分離開(kāi)發(fā)跨域登陸問(wèn)題
這篇文章主要介紹了詳解springboot和vue前后端分離開(kāi)發(fā)跨域登陸問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
JVM?運(yùn)行時(shí)數(shù)據(jù)區(qū)與JMM?內(nèi)存模型
這篇文章主要介紹了JVM?運(yùn)行時(shí)數(shù)據(jù)區(qū)與JMM?內(nèi)存模型,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值。需要的朋友可以參考一下2022-07-07
Java求出任意數(shù)字的各個(gè)位數(shù)之和方式
這篇文章主要介紹了Java求出任意數(shù)字的各個(gè)位數(shù)之和方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
springboot項(xiàng)目啟動(dòng)慢的問(wèn)題排查方式
這篇文章主要介紹了springboot項(xiàng)目啟動(dòng)慢的問(wèn)題排查方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
Java初學(xué)者之五子棋游戲?qū)崿F(xiàn)教程
這篇文章主要為大家詳細(xì)介紹了Java初學(xué)者之五子棋游戲?qū)崿F(xiàn)教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
Spring?Security自定義認(rèn)證邏輯實(shí)例詳解
這篇文章主要給大家介紹了關(guān)于Spring?Security自定義認(rèn)證邏輯的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01

