色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

Tomcat打破雙親委派機制實現(xiàn)隔離Web應(yīng)用的方法

瀏覽:123日期:2023-03-19 16:51:47
目錄
  • Tomcat類加載器的層次結(jié)構(gòu)
    • WebAppClassLoader
    • SharedClassLoader
    • CatalinaClassLoader
    • CommonClassLoader
  • Spring的加載問題
    • 線程上下文加載器
      • 總結(jié)

        Tomcat通過自定義類加載器WebAppClassLoader打破雙親委派,即重寫了JVM的類加載器ClassLoader的findClass方法和loadClass方法,以優(yōu)先加載Web應(yīng)用目錄下的類。

        Tomcat負(fù)責(zé)加載我們的Servlet類、加載Servlet所依賴的JAR包。Tomcat本身也是個Java程序,因此它需要加載自己的類和依賴的JAR包。

        若在Tomcat運行兩個Web應(yīng)用程序,它們有功能不同的同名Servlet,Tomcat需同時加載和管理這兩個同名的Servlet類,保證它們不會沖突。所以Web應(yīng)用之間的類需要隔離

        若兩個Web應(yīng)用都依賴同一三方j(luò)ar,比如Spring,則Spring jar被加載到內(nèi)存后,Tomcat要保證這兩個Web應(yīng)用能共享之,即Spring jar只被加載一次,否則隨著三方j(luò)ar增多,JVM的內(nèi)存會占用過大。
        所以,和 JVM 一樣,需要隔離Tomcat本身的類和Web應(yīng)用的類。

        Tomcat類加載器的層次結(jié)構(gòu)

        Tomcat的類加載器層次結(jié)構(gòu)

        前三個是加載器實例名,不是類名。

        WebAppClassLoader

        若使用JVM默認(rèn)的AppClassLoader加載Web應(yīng)用,AppClassLoader只能加載一個Servlet類,在加載第二個同名Servlet類時,AppClassLoader會返回第一個Servlet類的Class實例。
        因為在AppClassLoader眼里,同名Servlet類只能被加載一次。

        于是,Tomcat自定義了一個類加載器WebAppClassLoader, 并為每個Web應(yīng)用創(chuàng)建一個WebAppClassLoader實例。

        每個Web應(yīng)用自己的Java類和依賴的JAR包,分別放在WEB-INF/classesWEB-INF/lib目錄下,都是WebAppClassLoader加載的。

        Context容器組件對應(yīng)一個Web應(yīng)用,因此,每個Context容器創(chuàng)建和維護一個WebAppClassLoader加載器實例。
        不同加載器實例加載的類被認(rèn)為是不同的類,即使類名相同。這就相當(dāng)于在JVM內(nèi)部創(chuàng)建相互隔離的Java類空間,每個Web應(yīng)用都有自己的類空間,Web應(yīng)用之間通過各自的類加載器互相隔離。

        SharedClassLoader

        兩個Web應(yīng)用之間怎么共享庫類,并且不能重復(fù)加載相同的類?

        雙親委派機制的各子加載器都能通過父加載器去加載類,于是考慮把需共享的類放到父加載器的加載路徑。

        應(yīng)用程序即是通過該方式共享JRE核心類。
        Tomcat搞了個類加載器SharedClassLoader,作為WebAppClassLoader的父加載器,以加載Web應(yīng)用之間共享的類。

        若WebAppClassLoader未加載到某類,就委托父加載器SharedClassLoader去加載該類,SharedClassLoader會在指定目錄下加載共享類,之后返回給WebAppClassLoader,即可解決共享問題。

        CatalinaClassLoader

        如何隔離Tomcat本身的類和Web應(yīng)用的類?

        兄弟關(guān)系:兩個類加載器是平行的,它們可能擁有同一父加載器,但兩個兄弟類加載器加載的類是隔離的。

        于是,Tomcat搞了CatalinaClassLoader,專門加載Tomcat自身的類。

        問題是,當(dāng)Tomcat和各Web應(yīng)用之間需要共享一些類時該怎么辦?

        CommonClassLoader

        共享依舊靠父子關(guān)系。
        再增加個CommonClassLoader,作為CatalinaClassLoader和SharedClassLoader的父加載器。

        CommonClassLoader能加載的類都可被CatalinaClassLoader、SharedClassLoader 使用,而CatalinaClassLoader和SharedClassLoader能加載的類則與對方相互隔離。WebAppClassLoader可以使用SharedClassLoader加載到的類,但各個WebAppClassLoader實例之間相互隔離。

        Spring的加載問題

        JVM默認(rèn)情況下,若一個類由類加載器A加載,則該類的依賴類也由相同的類加載器加載。
        比如Spring作為一個Bean工廠,它需要創(chuàng)建業(yè)務(wù)類的實例,并且在創(chuàng)建業(yè)務(wù)類實例之前需要加載這些類。Spring是通過調(diào)用Class.forName來加載業(yè)務(wù)類的,我們來看一下forName的源碼:

        public static Class<?> forName(String className) {    Class<?> caller = Reflection.getCallerClass();    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);}

        會使用調(diào)用者,即Spring的加載器去加載業(yè)務(wù)類。

        Web應(yīng)用之間共享的jar可交給SharedClassLoader加載,以避免重復(fù)加載。Spring作為共享的三方j(luò)ar,本身由SharedClassLoader加載,Spring又要去加載業(yè)務(wù)類,按照前面那條規(guī)則,加載Spring的類加載器也會用來加載業(yè)務(wù)類,但是業(yè)務(wù)類在Web應(yīng)用目錄下,不在SharedClassLoader的加載路徑下,這該怎么辦呢?

        線程上下文加載器

        于是有了線程上下文加載器,一種類加載器傳遞機制。因為該類加載器保存在線程私有數(shù)據(jù)里,只要是同一個線程,一旦設(shè)置了線程上下文加載器,在線程后續(xù)執(zhí)行過程中就能把這個類加載器取出來用。因此Tomcat為每個Web應(yīng)用創(chuàng)建一個WebAppClassLoader類加載器,并在啟動Web應(yīng)用的線程里設(shè)置線程上下文加載器,這樣Spring在啟動時就將線程上下文加載器取出來,用來加載Bean。Spring取線程上下文加載的代碼如下:

        cl = Thread.currentThread().getContextClassLoader();

        在StandardContext的啟動方法,會將當(dāng)前線程的上下文加載器設(shè)置為WebAppClassLoader。

        啟動方法結(jié)束時,會恢復(fù)線程的上下文加載器:

        Thread.currentThread().setContextClassLoader(originalClassLoader);

        這是為什么呢?

        線程上下文加載器其實是線程的一個私有數(shù)據(jù),跟線程綁定,這個線程完成啟動Context組件后,會被回收到線程池,之后被用來做其他事情,為了不影響其他事情,需恢復(fù)之前的線程上下文加載器。
        優(yōu)先加載web應(yīng)用的類,當(dāng)加載完了再改回原來的。

        線程上下文的加載器就是指定子類加載器來加載具體的某個橋接類,比如JDBC的Driver的加載。

        總結(jié)

        Tomcat的Context組件為每個Web應(yīng)用創(chuàng)建一個WebAppClassLoader類加載器,由于不同類加載器實例加載的類是互相隔離的,因此達到了隔離Web應(yīng)用的目的,同時通過CommonClassLoader等父加載器來共享第三方JAR包。而共享的第三方JAR包怎么加載特定Web應(yīng)用的類呢?可以通過設(shè)置線程上下文加載器來解決。

        多個應(yīng)用共享的Java類文件和JAR包,分別放在Web容器指定的共享目錄:

        CommonClassLoader
        對應(yīng) <Tomcat>/common/*

        CatalinaClassLoader
        對應(yīng) <Tomcat >/server/*

        SharedClassLoader
        對應(yīng) <Tomcat >/shared/*

        WebAppClassloader
        對應(yīng) <Tomcat >/webapps/<app>/WEB-INF/*

        可以在Tomcat conf目錄下的Catalina.properties文件里配置各種類加載器的加載路徑。

        當(dāng)出現(xiàn)ClassNotFound錯誤時,應(yīng)該檢查你的類加載器是否正確。
        線程上下文加載器不僅僅可以用在Tomcat和Spring類加載的場景里,核心框架類需要加載具體實現(xiàn)類時都可以用到它,比如我們熟悉的JDBC就是通過上下文類加載器來加載不同的數(shù)據(jù)庫驅(qū)動的。

        到此這篇關(guān)于Tomcat打破雙親委派機制實現(xiàn)隔離Web應(yīng)用的方法的文章就介紹到這了,更多相關(guān)Tomcat 隔離Web應(yīng)用內(nèi)容請搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!

        標(biāo)簽: Tomcat
        相關(guān)文章:
        主站蜘蛛池模板: 国产精品久久久久网站 | 波多野结衣一区在线观看 | 国产高清视频在线 | 免费观看一级特黄欧美大片 | 北条麻妃在线一区二区 | 色www永久免费网站国产 | 日本国产免费一区不卡在线 | 久久久久久久久久毛片精品美女 | 色视频在线观看视频 | 亚洲综合视频在线观看 | 毛色毛片免费观看 | 亚洲精品综合久久中文字幕 | 成年人毛片 | 精品综合久久久久久98 | 久久午夜鲁丝片午夜精品 | 极品美女户外勾搭无套 | 亚洲精品国自产拍影院 | 免费视频成人国产精品网站 | 久久久久久免费一区二区三区 | 欧美大片一区二区三区 | 国产视频网站在线观看 | 亚洲第一在线播放 | 女人毛片a毛片久久人人 | 久久这里只有精品免费播放 | 99久久免费午夜国产精品 | 日本高清色www | 国产丝袜美女一区二区三区 | 久久男人的天堂色偷偷 | 中日毛片 | 制服丝袜怡红院 | 国产精品亚洲精品久久成人 | 一级片a级片 | 欧美男人天堂 | 国产一区在线免费观看 | 全免费a级毛片免费毛视频 全午夜免费一级毛片 | 456亚洲视频 | 免费看欧美成人性色生活片 | 国产成人av性色在线影院 | 中文字幕在线视频精品 | 日本一级大毛片a一 | 欧美日比视频 |