web server apache tomcat11-10-Class Loader

前言

整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本爲 v11 最新的版本。

開源項目

從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。

系列文章

web server apache tomcat11-01-官方文檔入門介紹

web server apache tomcat11-02-setup 啓動

web server apache tomcat11-03-deploy 如何部署

web server apache tomcat11-04-manager 如何管理?

web server apache tomcat11-06-Host Manager App -- Text Interface

web server apache tomcat11-07-Realm Configuration

web server apache tomcat11-08-JNDI Resources

web server apache tomcat11-09-JNDI Datasource

web server apache tomcat11-10-Class Loader

...

概述

像許多服務器應用程序一樣,Tomcat 安裝了各種類加載器(即實現 java.lang.ClassLoader 的類),以允許容器的不同部分以及在容器上運行的 Web 應用程序訪問不同的類和資源庫。

此機制用於提供 Servlet 規範 2.4 版中定義的功能,特別是第 9.4 節和第 9.6 節。

在 Java 環境中,類加載器被安排成父子樹。通常,當類加載器被要求加載特定的類或資源時,它首先將請求委託給父類加載器,然後僅在父類加載器無法找到請求的類或資源時才查看自己的存儲庫。

請注意,Web 應用程序類加載器的模型與此略有不同,如下所述,但主要原則相同。

當啓動 Tomcat 時,它創建了一組類加載器,這些類加載器按以下父子關係組織,其中父類加載器位於子類加載器之上:

      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ...

每個類加載器的特性,包括它們可見的類和資源的來源,將在以下部分詳細討論。

類加載器定義

如上圖所示,Tomcat 在初始化時創建以下類加載器:

  • Bootstrap — 此類加載器包含 Java 虛擬機提供的基本運行時類,以及位於系統擴展目錄 ($JAVA_HOME/jre/lib/ext) 中的任何 JAR 文件中的類。注意:一些 JVM 可能將其實現爲一個以上的類加載器,或者它可能根本不可見(作爲類加載器)。

  • System — 此類加載器通常是從 CLASSPATH 環境變量的內容初始化的。所有這些類對於 Tomcat 內部類和 Web 應用程序都是可見的。但是,標準的 Tomcat 啓動腳本 ($CATALINA_HOME/bin/catalina.sh 或 %CATALINA_HOME%\bin\catalina.bat) 完全忽略 CLASSPATH 環境變量本身的內容,並且改爲從以下存儲庫構建 System 類加載器:

    • $CATALINA_HOME/bin/bootstrap.jar — 包含用於初始化 Tomcat 服務器的 main() 方法,以及它依賴的類加載器實現類。
    • $CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jar — 日誌記錄實現類。這些包括對 java.util.logging API 的增強類,稱爲 Tomcat JULI,以及 Tomcat 內部使用的 Apache Commons Logging 庫的包重命名副本。有關更多詳細信息,請參閱日誌記錄文檔。
    • 如果 $CATALINA_BASE/bin 中存在 tomcat-juli.jar,則會使用它,而不是 $CATALINA_HOME/bin 中的 tomcat-juli.jar。在某些日誌記錄配置中,這很有用。
    • $CATALINA_HOME/bin/commons-daemon.jar — 來自 Apache Commons Daemon 項目的類。此 JAR 文件不包含在 catalina.bat|.sh 腳本構建的 CLASSPATH 中,但是在 bootstrap.jar 的清單文件中引用了它。
  • Common — 此類加載器包含了對 Tomcat 內部類和所有 Web 應用程序都可見的其他類。

    通常情況下,應用程序類不應放在此處。此類加載器搜索的位置由 $CATALINA_BASE/conf/catalina.properties 中的 common.loader 屬性定義。默認設置將按照它們列出的順序搜索以下位置:

    • $CATALINA_BASE/lib 中未打包的類和資源
    • $CATALINA_BASE/lib 中的 JAR 文件
    • $CATALINA_HOME/lib 中未打包的類和資源
    • $CATALINA_HOME/lib 中的 JAR 文件

默認情況下,這包括以下內容:

  • annotations-api.jar — Jakarta Annotations 2.1.1 類。
  • catalina.jar — Tomcat 的 Catalina servlet 容器部分的實現。
  • catalina-ant.jar — 可選。用於與 Manager web 應用程序一起使用的 Tomcat Catalina Ant 任務。
  • catalina-ha.jar — 可

選。基於 Tribes 構建的提供會話集羣功能的高可用性包。

  • catalina-ssi.jar — 可選。服務器端包含模塊。

  • catalina-storeconfig.jar — 可選。從當前狀態生成 XML 配置文件。

  • catalina-tribes.jar — 可選。高可用性包使用的組通信包。

  • ecj-*.jar — 可選。用於將 JSP 編譯爲 Servlet 的 Eclipse JDT Java 編譯器。

  • el-api.jar — 可選。EL 6.0 API。

  • jakartaee-migration-*-shaded.jar — 可選。提供將 Web 應用程序從 Java EE 8 轉換爲 Jakarta EE 9 的功能。

  • jasper.jar — 可選。Tomcat Jasper JSP 編譯器和運行時。

  • jasper-el.jar — 可選。Tomcat EL 實現。

  • jaspic-api.jar — Jakarta Authentication 3.0 API。

  • jsp-api.jar — 可選。Jakarta Pages 4.0 API。

  • servlet-api.jar — Jakarta Servlet 6.1 API。

  • tomcat-api.jar — Tomcat 定義的幾個接口。

  • tomcat-coyote.jar — Tomcat 連接器和實用程序類。

  • tomcat-dbcp.jar — 可選。基於 Apache Commons Pool 2 和 Apache Commons DBCP 2 的包重命名副本的數據庫連接池實現。

  • tomcat-i18n-**.jar — 可選的 JAR,包含其他語言的資源包。由於默認包含了每個單獨 JAR 中的默認包,因此如果不需要對消息進行國際化,則可以安全地刪除它們。

  • tomcat-jdbc.jar — 可選。另一種數據庫連接池實現,稱爲 Tomcat JDBC 池。有關更多詳細信息,請參閱文檔。

  • tomcat-jni.jar — 提供與 Tomcat Native 庫的集成。

  • tomcat-util.jar — Apache Tomcat 各個組件使用的公共類。

  • tomcat-util-scan.jar — 提供 Tomcat 使用的類掃描功能。

  • tomcat-websocket.jar — 可選。Jakarta WebSocket 2.1 實現。

  • websocket-api.jar — 可選。Jakarta WebSocket 2.1 API。

  • websocket-client-api.jar — 可選。Jakarta WebSocket 2.1 客戶端 API。

  • WebappX — 爲部署在單個 Tomcat 實例中的每個 Web 應用程序創建一個類加載器。您的 Web 應用程序的 /WEB-INF/classes 目錄中的所有未打包的類和資源,以及您的 Web 應用程序的 /WEB-INF/lib 目錄下的 JAR 文件中的類和資源,都會對該 Web 應用程序可見,但對其他 Web 應用程序不可見。

如上所述,Web 應用程序類加載器與默認的 Java 委託模型有所不同(根據 Servlet 規範 2.4 第 9.7.2 節 Web 應用程序類加載器的建議)。當處理對 Web 應用程序的 WebappX 類加載器的加載類的請求時,此類加載器首先會查找本地存儲庫,而不是委託給父級再查找。但也有一些例外。JRE 基本類的一部分無法被覆蓋。有一些例外,比如可以使用可升級模塊功能覆蓋的 XML 解析器組件。最後,對於由 Tomcat 實現的規範(Servlet、JSP、EL、WebSocket),Web 應用程序類加載器始終首先委託。Tomcat 中的所有其他類加載器都遵循通常的委派模式。

因此,從 Web 應用程序的角度來看,類或資源加載按以下順序查找存儲庫:

  1. JVM 的 Bootstrap 類
  2. 您的 Web 應用程序的 /WEB-INF/classes
  3. 您的 Web 應用程序的 /WEB-INF/lib/*.jar
  4. System 類加載器類(上文描述)
  5. Common 類加載器類(上文描述)

如果 Web 應用程序類加載器配置爲 <Loader delegate="true"/>,則順序變爲:

  1. JVM 的 Bootstrap 類
  2. System 類加載器類(上文描述)
  3. Common 類加載器類(上文描述)
  4. 您的 Web 應用程序的 /WEB-INF/classes
  5. 您的 Web 應用程序的 /WEB-INF/lib/*.jar

XML解析器和Java

在舊版本的Tomcat中,您可以簡單地替換Tomcat庫目錄中的XML解析器,以更改所有Web應用程序使用的解析器。然而,在運行現代版本的Java時,這種技術將不會有效,因爲通常的類加載器委託過程總是會優先選擇JDK內部的實現,而不是這個解析器。

Java支持一種稱爲可升級模塊的機制,允許替換在JCP之外創建的API(即W3C的DOM和SAX)。它還可以用於更新XML解析器的實現。

請注意,覆蓋任何JRE組件都存在風險。如果覆蓋組件不提供100%兼容的API(例如,Xerces提供的API與JRE提供的XML API不完全兼容),那麼Tomcat和/或部署的應用程序可能會遇到錯誤。

高級配置

還可以配置更復雜的類加載器層次結構。請參見下面的圖表。默認情況下,服務器和共享類加載器未定義,並且使用上面顯示的簡化層次結構。可以通過在 conf/catalina.properties 中定義 server.loader 和/或 shared.loader 屬性的值來使用此更復雜的層次結構。

  Bootstrap
      |
    System
      |
    Common
     /  \
Server  Shared
         /  \
   Webapp1  Webapp2 ...

服務器類加載器僅對Tomcat內部可見,對Web應用程序完全不可見。

共享類加載器對所有Web應用程序可見,可用於在所有Web應用程序之間共享代碼。但是,對此共享代碼的任何更新都將需要重新啓動Tomcat。

參考資料

https://tomcat.apache.org/tomcat-11.0-doc/class-loader-howto.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章