jvm雙親委派 vs 破壞雙親委派理解加載器的權(quán)責(zé)分配
雙親委派模型
對(duì)于任意一個(gè)類,都需要由加載它的類加載器和這個(gè)類本身來(lái)一同確立其在Java虛擬機(jī)中的唯一性。
為什么需要雙親委派
如果不是同一個(gè)類加載器加載,即使是相同的class文件,也會(huì)出現(xiàn)判斷不相同的情況,從而引發(fā)一些意想不到的情況,為了保證相同的class文件,在使用的時(shí)候,是相同的對(duì)象,jvm設(shè)計(jì)的時(shí)候,采用了雙親委派的方式來(lái)加載類。
雙親委派好處
- 避免同一個(gè)類被多次加載;
- 每個(gè)加載器只能加載自己范圍內(nèi)的類;
缺點(diǎn):
頂層的啟動(dòng)類加載器的代碼無(wú)法訪問到底層的類加載器。
每一個(gè)類都有一個(gè)對(duì)應(yīng)它的類加載器。系統(tǒng)中的 ClassLoder 在協(xié)同工作的時(shí)候會(huì)默認(rèn)使用雙親委派模型 。即在類加載的時(shí)候,系統(tǒng)會(huì)首先判斷當(dāng)前類是否被加載過(guò)。已經(jīng)被加載的類會(huì)直接返回,否則才會(huì)嘗試加載。類加載的時(shí)候,首先會(huì)把該請(qǐng)求委派該父類加載器的 loadClass() 處理,因此所有的請(qǐng)求最終都應(yīng)該傳送到頂層的啟動(dòng)類加載器 BootstrapClassLoader中。當(dāng)父類加載器無(wú)法處理時(shí),才由自己來(lái)處理。特別當(dāng)父類加載器為null時(shí),會(huì)使用啟動(dòng)類加載器 BootstrapClassLoader 作為父類加載器。
父類加載器有自己的加載范圍,范圍內(nèi)沒有找到,則不加載,并返回給子類。
jvm提供了三種系統(tǒng)加載器:
- 啟動(dòng)類加載器(Bootstrap ClassLoader):C++實(shí)現(xiàn),在java里無(wú)法獲取,負(fù)責(zé)加載/lib下的類。
- 擴(kuò)展類加載器(Extension ClassLoader): Java實(shí)現(xiàn),可以在java里獲取,負(fù)責(zé)加載/lib/ext下的類。
- 系統(tǒng)類加載器/應(yīng)用程序類加載器(Application ClassLoader):是與我們接觸對(duì)多的類加載器,我們寫的代碼默認(rèn)就是由它來(lái)加載,ClassLoader.getSystemClassLoader返回的就是它。
破壞雙親委派
為什么需要破壞雙親委派?
因?yàn)樵谀承┣闆r下父類加載器需要委托子類加載器去加載class文件。受到加載范圍的限制,父類加載器無(wú)法加載到需要的文件,以Driver接口為例,由于Driver接口定義在jdk當(dāng)中的,而其實(shí)現(xiàn)由各個(gè)數(shù)據(jù)庫(kù)的服務(wù)商來(lái)提供,比如mysql的就寫了MySQL Connector,那么問題就來(lái)了,DriverManager(也由jdk提供)要加載各個(gè)實(shí)現(xiàn)了Driver接口的實(shí)現(xiàn)類,然后進(jìn)行管理,但是DriverManager由啟動(dòng)類加載器加載,只能記載JAVA_HOME的lib下文件,而其實(shí)現(xiàn)是由服務(wù)商提供的,由系統(tǒng)類加載器加載,這個(gè)時(shí)候就需要啟動(dòng)類加載器來(lái)委托子類來(lái)加載Driver實(shí)現(xiàn),從而破壞了雙親委派,這里僅僅是舉了破壞雙親委派的其中一個(gè)情況。
破壞雙親委派的實(shí)現(xiàn)
我們結(jié)合Driver來(lái)看一下在spi(Service Provider Inteface)中如何實(shí)現(xiàn)破壞雙親委派。
先從DriverManager開始看,平時(shí)我們通過(guò)DriverManager來(lái)獲取數(shù)據(jù)庫(kù)的Connection:
在調(diào)用DriverManager的時(shí)候,會(huì)先初始化類,調(diào)用其中的靜態(tài)塊:
可以看到,load方法調(diào)用獲取了當(dāng)前線程中的上下文類加載器,那么上下文類加載器放的是什么加載器呢?
在sun.misc.Launcher中,我們找到了答案,在Launcher初始化的時(shí)候,會(huì)獲取AppClassLoader,然后將其設(shè)置為上下文類加載器,而這個(gè)AppClassLoader,就是之前上文提到的系統(tǒng)類加載器Application ClassLoader,所以上下文類加載器默認(rèn)情況下就是系統(tǒng)加載器。
以上就是淺談jvm雙親委派和破壞雙親委派的詳細(xì)內(nèi)容,更多關(guān)于jvm雙親委派的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談java中為什么實(shí)體類需要實(shí)現(xiàn)序列化
下面小編就為大家?guī)?lái)一篇淺談java中為什么實(shí)體類需要實(shí)現(xiàn)序列化。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05解決RedisTemplate的key默認(rèn)序列化器的問題
這篇文章主要介紹了解決RedisTemplate的key默認(rèn)序列化器的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03Mybatis使用typeHandler加密的實(shí)現(xiàn)
本文詳細(xì)介紹了如何在Mybatis中使用typeHandler對(duì)特定字段進(jìn)行加密處理,涵蓋了從引入依賴、配置Mybatis,到實(shí)現(xiàn)typeHandler繼承類和配置mapper層的詳細(xì)步驟,為需要在項(xiàng)目中實(shí)現(xiàn)字段加密的開發(fā)者提供了參考和借鑒2024-09-09Java 實(shí)戰(zhàn)項(xiàng)目錘煉之在線購(gòu)書商城系統(tǒng)的實(shí)現(xiàn)流程
讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+jsp+mysql+servlet+ajax實(shí)現(xiàn)一個(gè)在線購(gòu)書商城系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-11-11詳解MyBatisPlus如何實(shí)現(xiàn)分頁(yè)和查詢操作
這篇文章主要為大家詳細(xì)介紹了MyBatisPlus是如何實(shí)現(xiàn)分頁(yè)和查詢操作的,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定的幫助,需要的可以參考一下2022-05-05Java實(shí)現(xiàn)二分查找算法實(shí)例分析
這篇文章主要介紹了Java實(shí)現(xiàn)二分查找算法,實(shí)例分析了二分查找算法的原理與相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07Spring MVC 處理一個(gè)請(qǐng)求的流程
Spring MVC是Spring系列框架中使用頻率最高的部分。不管是Spring Boot還是傳統(tǒng)的Spring項(xiàng)目,只要是Web項(xiàng)目都會(huì)使用到Spring MVC部分。因此程序員一定要熟練掌握MVC部分。本篇博客簡(jiǎn)要分析Spring MVC處理一個(gè)請(qǐng)求的流程。2021-02-02