類別載入器操作指南

目錄

概觀

與許多伺服器應用程式一樣,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.jarApache 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 — 選用。Tomcat Catalina Ant 任務,用於處理 Manager 網路應用程式。
    • catalina-ha.jar — 選用。高可用性套件,提供建置在 Tribes 上的會話叢集功能。
    • catalina-ssi.jar — 選用。伺服器端包含模組。
    • catalina-storeconfig.jar — 選用。從目前狀態產生 XML 組態檔案。
    • catalina-tribes.jar — 選用。高可用性套件使用的群組通訊套件。
    • ecj-*.jar — 選用。Eclipse JDT Java 編譯器,用於將 JSP 編譯為 Servlet。
    • el-api.jar — 選用。EL 5.0 API。
    • jakartaee-migration-*-shaded.jar — 選用。提供將網路應用程式從 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 3.1 API。
    • servlet-api.jar — Jakarta Servlet 6.0 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 中,因此如果不需要訊息的國際化,可以安全地移除這些 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 Client API
  • WebappX — 為部署在單一 Tomcat 執行個體中的每個網路應用程式建立一個類別載入器。網路應用程式的 /WEB-INF/classes 目錄中的所有解壓縮類別和資源,以及網路應用程式 /WEB-INF/lib 目錄下 JAR 檔案中的類別和資源,都對此網路應用程式可見,但對其他網路應用程式不可見。

如上所述,Web 應用程式類別載入器偏離預設 Java 委派模型(根據 Servlet 規範第 2.4 版第 9.7.2 節 Web 應用程式類別載入器的建議)。當處理載入類別的請求時,來自 Web 應用程式的 WebappX 類別載入器將會**首先**在本地儲存庫中尋找,而不是在尋找之前委派。有一些例外。JRE 基礎類別的一部分的類別無法覆寫。有一些例外,例如可以使用可升級模組功能覆寫的 XML 解析器元件。最後,Web 應用程式類別載入器將始終首先委派 Tomcat 實作的 Jakarta EE API 類別(Servlet、JSP、EL、WebSocket)。Tomcat 中的所有其他類別載入器遵循一般的委派模式。

因此,從 Web 應用程式的角度來看,類別或資源載入會依序在下列儲存庫中尋找

  • JVM 的 Bootstrap 類別
  • Web 應用程式的 /WEB-INF/classes
  • Web 應用程式的 /WEB-INF/lib/*.jar
  • 系統類別載入器類別(如上所述)
  • 共用類別載入器類別(如上所述)

如果 Web 應用程式類別載入器已使用 <Loader delegate="true"/>設定,則順序會變成

  • JVM 的 Bootstrap 類別
  • 系統類別載入器類別(如上所述)
  • 共用類別載入器類別(如上所述)
  • Web 應用程式的 /WEB-INF/classes
  • 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 不 100% 相容),則 Tomcat 和/或已部署的應用程式可能會發生錯誤。

在安全性管理員下執行

在安全管理員底下執行時,允許載入類別的位置也將取決於您的政策檔案內容。請參閱 安全管理員操作指南 以取得更多資訊。

進階組態

也可以設定更複雜的類別載入器階層。請參閱下方的圖表。預設情況下,未定義伺服器共用類別載入器,並使用上面顯示的簡化階層。此更複雜的階層可能會透過在 conf/catalina.properties 中定義 server.loader 和/或 shared.loader 屬性的值來使用。


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

伺服器類別載入器僅對 Tomcat 內部可見,且對 Web 應用程式完全不可見。

Shared 類別載入器對所有 Web 應用程式都可見,且可用於在所有 Web 應用程式中共用程式碼。不過,對此共用程式碼的任何更新都需要重新啟動 Tomcat。