<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JDK為何自己先破壞雙親委派模型?

          共 2614字,需瀏覽 6分鐘

           ·

          2021-01-20 22:17


          ? 點(diǎn)擊上方“JavaEdge”,關(guān)注公眾號(hào)

          設(shè)為“星標(biāo)”,好文章不錯(cuò)過!


          說是雙親,其實(shí)多級(jí)單親,無奈迎合歷史的錯(cuò)誤翻譯吧。


          1 工作流程



          • 當(dāng)一個(gè)類加載器收到一個(gè)類加載請(qǐng)求 在 JDK9 后,會(huì)首先搜索它的內(nèi)建加載器定義的所有“具名模塊”:

            • 如果找到合適的模塊定義,將會(huì)使用該加載器來加載

            • 如果未找到,則會(huì)將該請(qǐng)求委派給父級(jí)加載器去加載

          • 因此所有的類加載請(qǐng)求最終都應(yīng)該被傳入到啟動(dòng)類加載器(Bootstrap ClassLoader)中,只有當(dāng)父級(jí)加載器反饋無法完成這個(gè)列的加載請(qǐng)求時(shí)(它的搜索范圍內(nèi)不存在這個(gè)類),子級(jí)加載器才嘗試加載。

          在類路徑下找到的類將成為這些加載器的無名模塊。

          這里的父子關(guān)系是組合而不是繼承




          雙親委派模型示意圖?






          雙親委派模型的優(yōu)點(diǎn)



          • 避免重復(fù)加載 父類已經(jīng)加載了,子類就不需要再次加載。eg,object 類。它存放在 rt.jar 中,無論哪個(gè)類加載器要加載這個(gè)類,最終都是委派給處于模型頂端的啟動(dòng)類加載器加載,因此 object 類在程序的各種加載環(huán)境中都是同一個(gè)類。

          • 更安全 解決了各個(gè)類加載器的基礎(chǔ)類的統(tǒng)一問題,如果不使用該種方式,那么用戶可以隨意定義類加載器來加載核心 API,會(huì)帶來安全隱患。


          雙親委派模型的實(shí)現(xiàn)



          類加載的方式



          1. 通過命令行啟動(dòng)應(yīng)用時(shí)由JVM初始化加載含有main()方法的主類。

          2. 通過Class.forName()方法動(dòng)態(tài)加載,會(huì)默認(rèn)執(zhí)行初始化塊(static{}),但是Class.forName(name,initialize,loader)中的initialze可指定是否要執(zhí)行初始化塊。

          3. 通過ClassLoader.loadClass()方法動(dòng)態(tài)加載,不會(huì)執(zhí)行初始化塊。


          自定義類加載器




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


          • 遵守雙親委派模型 繼承ClassLoader,重寫findClass()方法。

          • 破壞雙親委派模型 繼承ClassLoader,重寫loadClass()方法。

          通常我們推薦采用第一種方法自定義類加載器,最大程度上的遵守雙親委派模型。

          如果有一個(gè)類加載器能加載某個(gè)類,稱為定義類加載器,所有能成功返回該類的Class的類加載器都被稱為初始類加載器

          自定義類加載的目的是想要手動(dòng)控制類的加載,那除了通過自定義的類加載器來手動(dòng)加載類這種方式,還有其他的方式么?

          利用現(xiàn)成的類加載器進(jìn)行加載


          利用URLClassLoader進(jìn)行加載




          類加載實(shí)例


          命令行下執(zhí)行HelloWorld.java


          該段代碼大體經(jīng)過了一下步驟:

          1. 尋找jre目錄,尋找jvm.dll,并初始化JVM

          2. 產(chǎn)生一個(gè)Bootstrap ClassLoader

          3. Bootstrap ClassLoader加載器會(huì)加載他指定路徑下的java核心api,并且生成Extended ClassLoader加載器的實(shí)例,然后Extended ClassLoader會(huì)加載指定路徑下的擴(kuò)展java api,并將其父設(shè)置為Bootstrap ClassLoader

          4. Bootstrap ClassLoader生成Application ClassLoader,并將其父Loader設(shè)置為Extended ClassLoader

          5. 最后由AppClass ClassLoader加載classpath目錄下定義的類——HelloWorld類。

          我們上面談到 Extended ClassLoader和Application ClassLoader是通過Launcher來創(chuàng)建,現(xiàn)在我們?cè)倏纯丛创a

          破壞雙親委派模型




          雙親模型的問題


          父加載器無法向下識(shí)別子加載器加載的資源。




          JDBC

          如下證明 JDBC 是啟動(dòng)類加載器加載,但 mysql 驅(qū)動(dòng)是應(yīng)用類加載器。而 JDBC 運(yùn)行時(shí)又需要去訪問子類加載器加載的驅(qū)動(dòng),就破壞了該模型。??JDK 自己為解決該問題,引入線程上下問類加載器,可以通過Thread的setContextClassLoader()進(jìn)行設(shè)置

          當(dāng)為啟動(dòng)類加載器時(shí),使用當(dāng)前實(shí)際加載驅(qū)動(dòng)類的類加載器?




          熱替換



          比如OSGI的模塊化熱部署,它的類加載器就不再是嚴(yán)格按照雙親委派模型,很多 可能就在平級(jí)的類加載器中執(zhí)行了。


          FAQ



          1. ClassLoader通過一個(gè)類全限定名來獲取二進(jìn)制流,如果我們需通過自定義類加載其來加載一個(gè)Jar包的時(shí)候,難道要自己遍歷jar中的類,然后依次通過ClassLoader進(jìn)行加載嗎?或者說我們?cè)趺磥砑虞d一個(gè)jar包呢? 對(duì)于動(dòng)態(tài)加載jar而言,JVM默認(rèn)會(huì)使用第一次加載該jar中指定類的類加載器作為默認(rèn)的ClassLoader。

          假設(shè)我們現(xiàn)在存在名為sbbic的jar包,該包中存在ClassA和ClassB類(ClassA中沒有引用ClassB)。現(xiàn)在我們通過自定義的ClassLoaderA來加載在ClassA這個(gè)類,此時(shí)ClassLoaderA就成為sbbic.jar中其他類的默認(rèn)類加載器。即ClassB默認(rèn)也會(huì)通過ClassLoaderA去加載。

          1. 如果一個(gè)類引用的其他的類,那么這個(gè)其他的類由誰來加載?

          如果ClassA中引用了ClassB呢? 當(dāng)類加載器在加載ClassA的時(shí)候,發(fā)現(xiàn)引用了ClassB,此時(shí)類加載如果檢測(cè)到ClassB還沒有被加載,則先回去加載。當(dāng)ClassB加載完成后,繼續(xù)回來加載ClassA。即類會(huì)通過自身對(duì)應(yīng)的來加載其加載其他引用的類。

          1. 既然類可以由不同的加載器加載,那么如何確定兩個(gè)類如何是同一個(gè)類?

          JVM規(guī)定:對(duì)于任何一個(gè)類,都需要由加載它的類加載器和這個(gè)類本身一同確立在java虛擬機(jī)中的唯一性。即在jvm中判斷兩個(gè)類是否是同一個(gè)類取決于類加載和類本身,也就是同一個(gè)類加載器加載的同一份Class文件生成的Class對(duì)象才是相同的,類加載器不同,那么這兩個(gè)類一定不相同。


          往期推薦



          由于不知線程池的bug,某Java程序員叕被祭天

          程序員因重復(fù)記錄日志撐爆ELK被辭退!

          擁抱Kubernetes,再見了Spring Cloud

          云原生時(shí)代下的網(wǎng)關(guān)V.S反向代理




          目前交流群已有?800+人,旨在促進(jìn)技術(shù)交流,可關(guān)注公眾號(hào)添加筆者微信邀請(qǐng)進(jìn)群


          喜歡文章,點(diǎn)個(gè)“在看、點(diǎn)贊、分享”素質(zhì)三連支持一下~

          瀏覽 38
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青操日日干 | 精品人妻无码一区二区三区竹菊影视 | 91黄色一级电影 | a 在线观看免费 | 嫩操视频在线观看 |