日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat - 都说Tomcat违背了双亲委派机制,到底对不对?

發布時間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat - 都说Tomcat违背了双亲委派机制,到底对不对? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 類加載的本質
  • JVM 雙親委派機制
    • BootstrapClassLoader(啟動類加載器)
    • ExtensionClassLoader
    • AppClassLoader
  • Tomcat的 類加載順序
    • Tomcat要解決什么問題?
    • Tomcat違反了雙親委派機制?
    • Tomcat加載機制小結
  • Tomcat 熱加載JasperLoader
  • 常見錯誤
    • NoClassDefFoundError
    • NoSuchMethodError
    • ClassCastException


類加載的本質

ClassLoader是用來加載 Class 的。它負責將 Class 的字節碼形式轉換成內存形式的 Class 對象。

字節碼可以來自于磁盤文件 *.class,也可以是 jar 包里的 *.class,也可以來自遠程服務器提供的字節流,字節碼的本質就是一個字節數組 []byte,它有特定的復雜的內部格式。

JVM 運行實例中會存在多個 ClassLoader,不同的 ClassLoader 會從不同的地方加載字節碼文件。

它可以從不同的文件目錄加載,也可以從不同的 jar 文件中加載,也可以從網絡上不同的靜態文件服務器來下載字節碼再加載。


JVM 雙親委派機制

Java1.2之后引入雙親委派模式 。

核心原理: 如果其中一個類加載器收到了類加載的請求,它并不會自己去加載而是會將該請求委托給父類的加載器去執行,如果父類加載器還存在父類加載器,則進一步向上委托,如此遞歸,請求最終到達頂層的啟動類加載器。

如果父類能加載,則直接返回,如果父類加載不了則交由子類加載,這就是雙親委派模式。

好處

  • 向上委托給父類加載,父類加載不了再自己加載
  • 避免重復加載,防止Java核心api被篡改

BootstrapClassLoader(啟動類加載器)

負責加載 JVM 運行時核心類,加載System.getProperty("sun.boot.class.path")所指定的路徑或jar


ExtensionClassLoader

負責加載 JVM 擴展類,比如 swing 系列、內置的 js 引擎、xml 解析器 等等,這些庫名通常以 javax 開頭,它們的 jar 包位于 JAVAHOME/lib/rt.jar文件中.
加載System.getProperty("java.ext.dirs")所指定的路徑或jar。

在使用Java運行程序時,也可以指定其搜索路徑,例如:java -Djava.ext.dirs=d:\projects\testproj\classes HelloWorld。


AppClassLoader

AppClassLoader才是直接面向我們用戶的加載器,它會加載 Classpath 環境變量里定義的路徑中的 jar 包和目錄。

我們自己編寫的代碼以及使用的第三方 jar 包通常都是由它來加載的。

加載System.getProperty("java.class.path")所指定的路徑或jar。

在使用Java運行程序時,也可以加上-cp來覆蓋原有的Classpath設置,例如: java -cp ./lavasoft/classes HelloWorld


Tomcat的 類加載順序

在Tomcat中,默認的行為是先嘗試在Bootstrap和Extension中進行類型加載,如果加載不到則在WebappClassLoader中進行加載,如果還是找不到則在Common中進行查找 .

Common是公共的包, tomcat可以外掛很多個webapps (tomcat和app分開部署) ,優先以webapps下的為主。

tomcat7 —> 默認 WebappClassLoader 類加載器
tomcat 8 ---->默認 ParallelWebappClassLoader 類加載器


Tomcat要解決什么問題?

作為一個Web容器,Tomcat要解決什么問題 , Tomcat 如果使用默認的雙親委派類加載機制能不能行?

  • 我們知道Tomcat可以部署多個應用,不同的應用程序可能會依賴同一個第三方類庫的不同版本,不能要求同一個類庫在同一個服務器只有一份,因此要保證每個應用程序的類庫都是獨立的,保證相互隔離 .

    舉個例子 假設APP1 使用的是 Spring4 , APP2 使用的是Spring5 , 毫無疑問 Spring4 和 Spring 5 肯定有 類的全路徑一樣的類吧,如果使用雙親委派 ,父加載器加載誰?

  • 部署在同一個web容器中相同的類庫相同的版本可以共享, 比如jdk的核心jar包,否則,如果服務器有n個應用程序,那么要有n份相同的類庫加載進虛擬機。

  • web容器 自己依賴的類庫 (tomcat lib目錄下),不能與應用程序的類庫混淆。基于安全考慮,應該讓容器的類庫和程序的類庫隔離開來。

  • web容器要支持jsp的修改, jsp 文件最終也是要編譯成class文件才能在虛擬機中運行, web容器需要支持 jsp 修改后不用重啟 ,就是熱加載的功能。

  • 結合上面的4個問題,我們看下雙親委派能不能支持?

    第一個問題,如果使用默認的類加載器機制,肯定是無法加載兩個相同類庫的不同版本的,如果使用雙親委派,讓父加載器去加載 ,不管你是什么版本的,只要你的全限定類名一樣,那肯定只有一份,APP 隔離 無法滿足

    第二個問題,默認的類加載器是能夠實現的,很好理解嘛, 就是雙親委派的功能,保證唯一性。

    第三個問題和第一個問題一樣。

    第四個問題, 要怎么實現jsp文件的熱加載呢? jsp 文件其實也就是class文件,那么如果修改了,但類名還是一樣,類加載器會直接取方法區中已經存在的,修改后的jsp是不會重新加載的。那么怎么辦呢?可以直接卸載掉這jsp文件的類加載器 .當一個jsp文件修改了,就直接卸載這個jsp類加載器。重新創建類加載器,重新加載jsp文件。 源碼詳見: org.apache.jasper.servlet.JasperLoader



    Tomcat違反了雙親委派機制?

    也不盡然,核心的Java的加載還是遵從雙親委派 。

    Tomcat中 各個web應用自己的類加載器(WebAppClassLoader)會優先加載,打破了雙親委派機制。加載不到時再交給commonClassLoader走雙親委托 .

    原因有二

    • 為了避免類沖突,每個 webapp 項目中各自使用的類庫要有隔離機制
    • 不同 webapp 項目支持共享某些類庫

    Tomcat加載機制小結

    當tomcat啟動時,會創建幾種類加載器:

  • Bootstrap 引導類加載器 : 加載JVM啟動所需的類,以及標準擴展類(位于jre/lib/ext下)

  • System 系統類加載器 : 加載tomcat啟動的類,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下


  • 4. webapp 應用類加載器: 每個應用在部署后,都會創建一個唯一的類加載器。該類加載器會加載位于 WEB-INF/lib下的jar文件中的class 和 WEB-INF/classes下的class文件。

  • Common 通用類加載器:加載tomcat使用以及應用通用的一些類,位于CATALINA_HOME/lib下,比如servlet-api.jar

  • 總之 當應用需要到某個類時,則會按照下面的順序進行類加載:

    1 使用bootstrap引導類加載器加載 (JVM 的東西 )

    2 使用system系統類加載器加載 (tomcat的啟動類Bootstrap包)

    3 使用WebAppClassLoader 加載 WEB-INF/classes (應用自定義的class)

    4 使用WebAppClassLoader 加載在WEB-INF/lib (應用的依賴包)

    5 使用common類加載器在CATALINA_HOME/lib中加載 (tomcat的依賴包,公共的,被各個應用共享的)


    Tomcat 熱加載JasperLoader

    原理:后臺啟動線程監聽jsp文件變化,如果變化了找到該jsp對應的servlet類的加載器引用(gcroot),重新生成新的JasperLoader加載器賦值給引用,然后加載新的jsp對應的servlet類,之前的那個加載器因為沒有gcroot引用了,下一次gc的時候會被銷毀。


    常見錯誤

    NoClassDefFoundError

    NoClassDefFoundError : 由于JVM或者類加載器實例嘗試加載類型的定義,但是該定義卻沒有找到,影響了執行路徑。

    換句話說,在編譯時這個類是能夠被找到的,但是在執行時卻沒有找到。


    NoSuchMethodError

    NoSuchMethodError代表這個類型確實存在,但是一個不正確的版本被加載了。 檢查該類中是否真的有對應的方法


    ClassCastException

    ClassCastException,在一個類加載器的情況下,一般出現這種錯誤都會是在轉型操作時,比如:A a = (A) method();,很容易判斷出來method()方法返回的類型不是類型A,但是在 JavaEE 多個類加載器的環境下可能會出現一些不好去定位的情況。

    總結

    以上是生活随笔為你收集整理的Tomcat - 都说Tomcat违背了双亲委派机制,到底对不对?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。