Tomcat 7 類加載器是如何實現的

Tomcat 7 類加載器是如何實現的

概述

與許多服務器應用程序同樣,Tomcat安裝了各類類加載器(即實現的類java.lang.ClassLoader),以容許容器的不一樣部分和容器上運行的Web應用程序訪問可用類和資源的不一樣存儲庫。此機制用於提供Servlet規範2.4版中定義的功能 - 特別是9.4和9.6節。html

在Java環境中,類加載器排列在父子樹中。一般,當要求類加載器加載特定的類或資源時,它首先將請求委託給父類加載器,而後僅在父類加載器找不到所請求的類或資源時查找它本身的存儲庫。 。請注意,Web應用程序類加載器的模型與此略有不一樣,以下所述,但主要原則是相同的。java

當Tomcat啓動時,它會建立一組類加載器,這些加載器被組織成如下父子關係,其中父類加載器位於子類加載器之上:web

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

這些類加載器的特徵,包括它們可見的類和資源的來源,將在下一節中詳細討論。數據庫

類加載器定義

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

    • Bootstrap - 此類加載器包含Java虛擬機提供的基本運行時類,以及System Extensions目錄($JAVA_HOME/jre/lib/ext)中存在的JAR文件中的任何類。 注意:一些JVM可能將其實現爲多個類加載器,或者它可能根本不可見(做爲類加載器)。
    • System - 此類加載器一般從CLASSPATH環境變量的內容初始化。Tomcat內部類和Web應用程序均可以看到全部這些類。可是,標準的Tomcat啓動腳本($CATALINA_HOME/bin/catalina.sh或 %CATALINA_HOME%bincatalina.bat)徹底忽略CLASSPATH環境變量自己的內容,而是從如下存儲庫構建System類加載器:
    1. $CATALINA_HOME/bin/bootstrap.jar - 包含用於初始化 Tomcat 服務器的main() 方法,以及它依賴的類加載器實現類。
    2. $CATALINA_BASE/bin/tomcat-juli.jar 或 $CATALINA_HOME/bin/tomcat-juli.jar - 記錄實現類。其中包括java.util.loggingAPI 的加強類 ,稱爲Tomcat JULI,以及Tomcat內部使用的Apache Commons Logging庫的軟件包重命名副本。有關詳細信息,請參閱日誌記錄

    若是tomcat-juli.jar是出如今 $CATALINA_BASE/bin 中,它被用來代替 $CATALINA_HOME/bin 中的那一個。它在某些日誌記錄配置中頗有用api

    1. $CATALINA_HOME/bin/commons-daemon.jar - 來自Apache Commons Daemon項目的類。這個JAR文件不存在於CLASSPATH 由腳本catalina.bat|.sh 構建,可是從bootstrap.jar的清單文件中引用。tomcat

      • Common - 此類加載器包含對Tomcat內部類和全部Web應用程序均可見的其餘類。

    一般狀況下,應用類應該不 放在這裏。此類由common.loader加載器搜索的位置$CATALINA_BASE/conf/catalina.properties 中的屬性定義。默認設置將按列出的順序搜索如下位置:安全

    1. 解壓縮的類和資源 $CATALINA_BASE/lib
    2. JAR文件 $CATALINA_BASE/lib
    3. 解壓縮的類和資源 $CATALINA_HOME/lib
    4. JAR文件 $CATALINA_HOME/lib

    默認狀況下,這包括如下內容:服務器

    annotations-api.jar - JavaEE註釋類。
    catalina.jar - Tomcat的Catalina servlet容器部分的實現。
    catalina-ant.jar - Tomcat Catalina Ant任務。
    catalina-ha.jar - 高可用性包。
    catalina-tribes.jar - 羣組通訊包。
    ecj - * .jar - Eclipse JDT Java編譯器。
    el-api.jar - EL 2.2 API。
    jasper.jar - Tomcat Jasper JSP編譯器和運行時。
    jasper-el.jar - Tomcat Jasper EL實現。
    jsp-api.jar - JSP 2.2 API。
    servlet-api.jar - Servlet 3.0 API。
    tomcat-api.jar - Tomcat定義的幾個接口。
    tomcat-coyote.jar - Tomcat鏈接器和實用程序類。
    tomcat-dbcp.jar - 基於包重命名的Apache Commons Pool和Apache Commons DBCP 1.x的數據庫鏈接池實現。
    tomcat-i18n - **。jar - 包含其餘語言資源包的可選JAR。因爲默認捆綁包也包含在每一個單獨的JAR中,所以若是不須要消息的國際化,則能夠安全地刪除它們。
    tomcat-jdbc.jar - 另外一種數據庫鏈接池實現,稱爲Tomcat JDBC池。有關詳細信息,請參閱 文檔
    tomcat-util.jar - Apache Tomcat的各類組件使用的公共類。
    tomcat7-websocket.jar - WebSocket 1.1實現
    websocket-api.jar - WebSocket 1.1 API
    WebappX - 爲部署在單個Tomcat實例中的每一個Web應用程序建立一個類加載器。/WEB-INF/classesWeb應用程序目錄中的全部解壓縮的類和資源,以及Web應用程序/WEB-INF/lib目錄下的JAR文件中的類和資源,都對此Web應用程序可見,但對其餘應用程序不可見。websocket

    如上所述,Web應用程序類加載器與默認Java委託模型不一樣(根據Servlet規範2.4版,第9.7.2節Web應用程序類加載器中的建議)。當加載從Web應用程序的一個類的請求WebappX被處理的類加載器,這個類加載器會在本地資源庫第一而不是在尋找以前委託。也有例外。做爲JRE基類的一部分的類不能被覆蓋。對於某些類(例如J2SE 1.4+中的XML解析器組件),Java承認的功能能夠用於Java 8.最後,類加載器將明確忽略包含Servlet API類的任何JAR文件 - 不包括此類Web應用程序中的JAR。Tomcat中的全部其餘類加載器都遵循一般的委託模式。

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

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

    若是配置了Web應用程序類加載器 , <Loader delegate="true"/> 則清單順序變爲:

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

    XML分析器和Java

    從Java 1.4開始,JRE中包含一個JAXP API和一個XML解析器。這會對但願使用本身的XML解析器的應用程序產生影響。

    在舊版本的Tomcat中,您只需替換Tomcat庫目錄中的XML解析器便可更改全部Web應用程序使用的解析器。可是,當您運行現代版本的 Java 時,此技術將無效,由於一般的類加載器委派過程將始終在JDK中選擇優先於此實現的實現。

    Java支持一種稱爲「支持標準覆蓋機制」的機制,以容許替換在JCP外部建立的API(即來自W3C的DOM和SAX)。它還可用於更新XML解析器實現。有關更多信息,請參閱: http: //docs.oracle.com/javase/1.5.0/docs/guide/standards/index.html。

    Tomcat經過-Djava.endorsed.dirs=$JAVA_ENDORSED_DIRS 在啓動容器的命令行中包含系統屬性設置來利用此機制 。此選項的默認值爲 $CATALINA_HOME/endorsed。默認狀況下不會建立此已簽名的目錄。請注意,Java 9再也不支持已承認的功能,而且只有在目錄$CATALINA_HOME/endorsed 存在或 JAVA_ENDORSED_DIRS 已設置變量 時纔會設置上述系統屬性。

    請注意,覆蓋任何JRE組件都存在風險。若是覆蓋組件未提供100%兼容的API(例如,Xerces提供的API與JRE提供的XML API不徹底兼容),則存在Tomcat和/或部署的應用程序將出現錯誤的風險。

    在安全管理器下運行

    在安全管理器下運行時,容許加載類的位置也取決於策略文件的內容。有關詳細信息,請參閱安全管理器HOW-TO。

    高級配置

    還能夠配置更復雜的類加載器層次結構。見下圖。默認狀況下, 未定義 Server 和 Shared 類加載器,並使用上面顯示的簡化層次結構。能夠經過定義 server.loader 和/或 shared.loader 屬性的值來使用這種更復雜的層次結構 conf/catalina.properties

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

    該服務器類加載器是惟一到Tomcat內部可見,而且是Web應用程序徹底不可見。

    所述 Common 類加載器是將全部的web應用程序可見,而且能夠在全部的 web 應用程序被用來共享代碼。可是,對此共享代碼的任何更新都須要從新啓動Tomcat

    相關文章
    相關標籤/搜索