<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>

          為什么 Tomcat 會破壞雙親委派機制?

          共 3363字,需瀏覽 7分鐘

           ·

          2022-02-15 13:14


          面試官要不你今天來詳細(xì)講講雙親委派機制?

          候選者:嗯,好的。

          候選者:上次提到了:class文件是通過「類加載器」裝載至JVM中的

          候選者:為了防止內(nèi)存中存在多份同樣的字節(jié)碼,使用了雙親委派機制(它不會自己去嘗試加載類,而是把請求委托給父加載器去完成,依次向上)

          候選者:JDK 中的本地方法類一般由根加載器(Bootstrp loader)裝載,JDK 中內(nèi)部實現(xiàn)的擴展類一般由擴展加載器(ExtClassLoader )實現(xiàn)裝載,而程序中的類文件則由系統(tǒng)加載器(AppClassLoader )實現(xiàn)裝載。

          候選者:這應(yīng)該很好理解吧?

          面試官:雀食(確實)!

          面試官順著話題,我想問問,打破雙親委派機制是什么意思?

          候選者:很好理解啊,意思就是:只要我加載類的時候,不是從APPClassLoader->Ext ClassLoader->BootStrap ClassLoader 這個順序找,那就算是打破了啊

          候選者:因為加載class核心的方法在LoaderClass類的loadClass方法上(雙親委派機制的核心實現(xiàn))

          候選者:那只要我自定義個ClassLoader,重寫loadClass方法(不依照往上開始尋找類加載器),那就算是打破雙親委派機制了。

          面試官:這么簡單?

          候選者:嗯,就是這么簡單

          面試官那你知道有哪個場景破壞了雙親委派機制嗎?

          候選者:最明顯的就Tomcat啊

          面試官:詳細(xì)說說?

          候選者:在初學(xué)時部署項目,我們是把war包放到tomcat的webapp下,這意味著一個tomcat可以運行多個Web應(yīng)用程序(:

          候選者:是吧?

          面試官:嗯..

          候選者:那假設(shè)我現(xiàn)在有兩個Web應(yīng)用程序,它們都有一個類,叫做User,并且它們的類全限定名都一樣,比如都是com.yyy.User。但是他們的具體實現(xiàn)是不一樣的

          候選者:那么Tomcat是如何保證它們是不會沖突的呢?

          候選者:答案就是,Tomcat給每個 Web 應(yīng)用創(chuàng)建一個類加載器實例(WebAppClassLoader),該加載器重寫了loadClass方法,優(yōu)先加載當(dāng)前應(yīng)用目錄下的類,如果當(dāng)前找不到了,才一層一層往上找(:

          候選者:那這樣就做到了Web應(yīng)用層級的隔離

          面試官嗯,那你還知道Tomcat還有別的類加載器嗎?

          候選者:嗯,知道的

          候選者:并不是Web應(yīng)用程序下的所有依賴都需要隔離的,比如Redis就可以Web應(yīng)用程序之間共享(如果有需要的話),因為如果版本相同,沒必要每個Web應(yīng)用程序都獨自加載一份啊。

          候選者:做法也很簡單,Tomcat就在WebAppClassLoader上加了個父類加載器(SharedClassLoader),如果WebAppClassLoader自身沒有加載到某個類,那就委托SharedClassLoader去加載。

          候選者:(無非就是把需要應(yīng)用程序之間需要共享的類放到一個共享目錄下嘛)

          面試官:嗯..

          候選者:為了隔絕Web應(yīng)用程序與Tomcat本身的類,又有類加載器(CatalinaClassLoader)來裝載Tomcat本身的依賴

          候選者:如果Tomcat本身的依賴和Web應(yīng)用還需要共享,那么還有類加載器(CommonClassLoader)來裝載進(jìn)而達(dá)到共享

          候選者:各個類加載器的加載目錄可以到tomcat的catalina.properties配置文件上查看

          候選者:我稍微畫下Tomcat的類加載結(jié)構(gòu)圖吧,不然有點抽象

          面試官:嗯,還可以,我聽懂了,有點意思。

          面試官順便,我想問下,JDBC你不是知道嗎,聽說它也是破壞了雙親委派模型的,你怎么理解的。

          候選者:Eumm,這個有沒有破壞,見仁見智吧。

          候選者:JDBC定義了接口,具體實現(xiàn)類由各個廠商進(jìn)行實現(xiàn)嘛(比如MySQL)

          候選者:類加載有個規(guī)則:如果一個類由類加載器A加載,那么這個類的依賴類也是由「相同的類加載器」加載。

          候選者:我們用JDBC的時候,是使用DriverManager進(jìn)而獲取Connection,DriverManager在java.sql包下,顯然是由BootStrap類加載器進(jìn)行裝載

          候選者:當(dāng)我們使用DriverManager.getConnection()時,得到的一定是廠商實現(xiàn)的類。

          候選者:但BootStrap ClassLoader會能加載到各個廠商實現(xiàn)的類嗎?

          候選者:顯然不可以啊,這些實現(xiàn)類又沒在java包中,怎么可能加載得到呢

          面試官:嗯..

          候選者:DriverManager的解決方案就是,在DriverManager初始化的時候,得到「線程上下文加載器」

          候選者:去獲取Connection的時候,是使用「線程上下文加載器」去加載Connection的,而這里的線程上下文加載器實際上還是App ClassLoader

          候選者:所以在獲取Connection的時候,還是先找Ext ClassLoader和BootStrap ClassLoader,只不過這倆加載器肯定是加載不到的,最終會由App ClassLoader進(jìn)行加載

          面試官:嗯..

          候選者:那這種情況,有的人覺得破壞了雙親委派機制,因為本來明明應(yīng)該是由BootStrap ClassLoader進(jìn)行加載的,結(jié)果你來了一手「線程上下文加載器」,改掉了「類加載器」

          候選者:有的人覺得沒破壞雙親委派機制,只是改成由「線程上下文加載器」進(jìn)行類加載,但還是遵守著:「依次往上找父類加載器進(jìn)行加載,都找不到時才由自身加載」。認(rèn)為”原則”上是沒變的。

          面試官:那我了解了

          本文總結(jié)

          • 前置知識: JDK中默認(rèn)類加載器有三個:AppClassLoader、Ext ClassLoader、BootStrap ClassLoader。AppClassLoader的父加載器為Ext ClassLoader、Ext ClassLoader的父加載器為BootStrap ClassLoader。這里的父子關(guān)系并不是通過繼承實現(xiàn)的,而是組合。

          • 什么是雙親委派機制: 加載器在加載過程中,先把類交由父類加載器進(jìn)行加載,父類加載器沒找到才由自身加載。

          • 雙親委派機制目的: 為了防止內(nèi)存中存在多份同樣的字節(jié)碼(安全)

          • 類加載規(guī)則: 如果一個類由類加載器A加載,那么這個類的依賴類也是由「相同的類加載器」加載。

          • 如何打破雙親委派機制: 自定義ClassLoader,重寫loadClass方法(只要不依次往上交給父加載器進(jìn)行加載,就算是打破雙親委派機制)

          • 打破雙親委派機制案例: Tomcat

            • 為了Web應(yīng)用程序類之間隔離,為每個應(yīng)用程序創(chuàng)建WebAppClassLoader類加載器
            • 為了Web應(yīng)用程序類之間共享,把ShareClassLoader作為WebAppClassLoader的父類加載器,如果WebAppClassLoader加載器找不到,則嘗試用ShareClassLoader進(jìn)行加載
            • 為了Tomcat本身與Web應(yīng)用程序類隔離,用CatalinaClassLoader類加載器進(jìn)行隔離,CatalinaClassLoader加載Tomcat本身的類
            • 為了Tomcat與Web應(yīng)用程序類共享,用CommonClassLoader作為CatalinaClassLoader和ShareClassLoader的父類加載器
            • ShareClassLoader、CatalinaClassLoader、CommonClassLoader的目錄可以在Tomcat的catalina.properties進(jìn)行配置
          • 線程上下文加載器: 由于類加載的規(guī)則,很可能導(dǎo)致父加載器加載時依賴子加載器的類,導(dǎo)致無法加載成功(BootStrap ClassLoader無法加載第三方庫的類),所以存在「線程上下文加載器」來進(jìn)行加載。


          本文作者 3y,一年 CRUD 經(jīng)驗用十年的 markdown 程序員,常年被譽為優(yōu)質(zhì)八股文選手。最近在從零寫消息推送平臺開源項目,已收獲 1k stars,歡迎關(guān)注。
          瀏覽 85
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  东京热人人操 | 五月丁香色色网 | 卡一卡二无码 | 日韩在线视频第一页 | 亚洲AV激情无码专区在线播放 |