類別載入器操作指南
目錄
概觀
與許多伺服器應用程式一樣,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 — 選用。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。