為了賬號安全,請及時綁定郵箱和手機立即綁定

Tomcat 架構分析(二) ClassLoader詳解

2017.12.07 14:43 3524瀏覽
Tomcat 架構分析(二) ClassLoader詳解

圖片描述

前言:

上一節提到,Tomcat的五個子模塊:Jsper模塊、Servlet和Jsp模塊、Catalina模塊、Connector模塊、Resource模塊,本節是對lib包下的詳細講解,以及Tomcat是如何加載類(ClassLoader)

1.簡介

與許多服務器應用程序一樣,Tomcat安裝了各種類裝入器(也就是實現java.lang.classloader的類),以允許容器的不同部分和在容器上運行的web應用程序訪問不同的可用類和資源的存儲庫。該機制用于提供Servlet規范中定義的功能。

在Java環境中,類裝入器被安排在父-子樹中。通常,當一個類裝入器被要求裝入一個特定的類或資源時,它首先將請求委托給父類裝入器,然后只在父類裝入器(s)不能找到所請求的類或資源時才查找它自己的存儲庫。請注意,web應用程序類加載器的模型與下面略有不同,但主要原則是相同的。

在啟動Tomcat時,它會創建一組類裝入器,這些裝入器會被組織到下面的父-子關系中,其中父類裝入器位于子類裝入器之上:

2.類加載的定義

圖片描述

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

1.Bootstrap —— 這個類裝入器包含Java虛擬機提供的基本運行時類,以及從系統擴展目錄(javahome/jre/lib/ext)中提供的JAR文件的任何類。注意:有些jvm可能會將它作為一個以上的類裝入器來實現,或者它可能不可見(作為一個類裝入器)。

2.System —— 這個類裝入器通常從CLASSPATH環境變量的內容中初始化。對于Tomcat內部類和web應用程序,所有這些類都是可見的。
然而,標準的Tomcat啟動腳本($catalinahome/bin/catalina.sh或%catalinhome%bin catalina.bat)完全忽略CLASSPATH環境變量本身的內容,而是從以下存儲庫構建系統類裝入器:

$CATALINA_HOME/bin/bootstrap.jar — 包含用于初始化Tomcat服務器的main()方法,以及它所依賴的類裝入器實現類。

$CATALINA_BASE/bin/tomcat-juli.jar or $CATALINA_HOME/bin/tomcat-juli.jar — 日志實現類。這些包括對java.util的增強類。被稱為Tomcat JULI的日志API,以及由Tomcat內部使用的Apache Commons日志庫的一個包重命名的副本。

如果tomcat-juli.jar是在$CATALINA_BASE/bin 中使用的,它是用在 $CATALINA_HOME/bin 中使用的。它在某些日志配置中很有用

$CATALINA_HOME/bin/commons-daemon.jar — 來自Apache Commons守護進程項目的類。這個JAR文件不在由catalina.bat|.sh 構建的類路徑中,但是是從bootstrap.jar的文件中引用的。

3.Common ——這個類裝入器包含了對Tomcat內部類和所有web應用程序都可見的其他類。

通常,應用程序類不應該放在這里。這個類裝入器的位置是由 common.loader perporties 定義 在 $CATALINA_BASE/conf/catalina.properties。
默認設置將按照以下順序搜索以下位置:

* 未打包的 classes and resources in $CATALINA_BASE/lib
* JAR files in $CATALINA_BASE/lib
* 未打包的 classes and resources in $CATALINA_HOME/lib
* JAR files in $CATALINA_HOME/lib

*如圖,為windows解壓后lib文件下(.jar包)分布情況:**
圖片描述

默認的,包括以下文件:

annotations-api.jar — JavaEE注解類

catalina.jar — 實現Tomcat Catalina Servlet容器的一部分

catalina-ant.jar — Tomcat Catalina 編譯任務.

catalina-ha.jar — 高可用性的包.

catalina-storeconfig.jar — 當前版本的一些配置文件

catalina-tribes.jar — 支持通訊的文件.

ecj-*.jar — Java編譯器Eclipse提供的API.

el-api.jar — EL表達式 3.0 API.

jasper.jar — Tomcat解析JSP的編譯和運行.

jasper-el.jar — Tomcat解析EL表達式的實現。

jsp-api.jar — JSP 2.3 API.

servlet-api.jar — Servlet 3.1 API.

tomcat-api.jar — Tomcat定義的一些服務.

tomcat-coyote.jar — Tomcat connectors(連接器) and 通用的classes.

tomcat-dbcp.jar — Database connection pool(數據庫連接池) implementation based on package-renamed copy of Apache Commons Pool and Apache Commons DBCP.

tomcat-i18n-**.jar — Optional JARs containing resource bundles for other languages. As default bundles are also included in each individual JAR, they can be safely removed if no internationalization of messages is needed.

tomcat-jdbc.jar — An alternative database connection pool implementation, known as Tomcat JDBC pool. See documentation for more details.

tomcat-util.jar — Common classes used by various components of Apache Tomcat.
tomcat-websocket.jar — WebSocket 1.1 implementation

websocket-api.jar — WebSocket 1.1 API

4.WebappX ——為每個web應用程序創建一個類裝入器,該應用程序部署在一個Tomcat實例中。在web應用程序的/web/web/類目錄中所有未打包的類和資源,以及web應用程序/web應用程序/lib目錄下的JAR文件中的類和資源,都可以在這個web應用程序中看到,而不是其他的。

正如上面所提到的,web應用程序類加載器與默認的Java委托模型(按照Servlet規范中的建議,web應用程序類加載器的建議)不同。當請求從web應用程序的WebappX類加載器加載一個類時,這個類裝入器將首先在本地存儲庫中查找,而不是在查找之前進行委托。也有例外。屬于JRE基類的類不能被覆蓋。有一些例外,比如XML解析器組件,可以使用適當的JVM特性覆蓋,這是Java小于=8所支持的標準覆蓋特性,以及用于Java 9+的可升級模塊特性。最后,web應用程序類加載器將總是為JavaEE API類的第一個代理,為Tomcat(Servlet、JSP、EL、WebSocket)所實現的規范。Tomcat中的所有其他類裝入器都遵循通常的代理模式。
因此,從web應用程序的角度來看,類或資源加載在以下存儲庫中如下所顯示的:

Bootstrap classes of your JVM

/WEB-INF/classes of your web application

/WEB-INF/lib/*.jar of your web application

System class loader classes (described above)

Common class loader classes (described above)
如果Web應用程序配置了 "<Loader delegate="true"/>", 則ClassLoader的加載順序為:

Bootstrap classes of your JVM

System class loader classes (described above)

Common class loader classes (described above)

/WEB-INF/classes of your web application

/WEB-INF/lib/*.jar of your web application

3.XML的分析與Java的關系

從Java 1.4開始,一個JAXP api的副本和一個XML解析器被打包在JRE中。這對希望使用自己的XML解析器的應用程序產生了影響。

在舊版本的Tomcat中,您可以簡單地替換Tomcat庫目錄中的XML解析器來更改所有web應用程序使用的解析器。然而,當您正在運行Java的現代版本時,這種技術將不會有效,因為通常的類裝入器委托過程將始終選擇JDK中的實現,而不是這個。

Java8或以下支持一種稱為“支持的標準覆蓋機制”的機制,允許替換在JCP之外創建的api(即來自W3C的DOM和SAX)。它還可以用于更新XML解析器實現。有關更多信息,請參見:http://docs.oracle.com/javase/1.5.0/docs/guide/standards/index.html。對于Java 9+,使用可升級的模塊特性。

Tomcat利用了支持的機制,包括系統屬性設置——djava.背書。在啟動容器的命令行中,dirs=$javaendorseddirs。這個選項的默認值是$catalinahome/背書。這個支持的目錄不是默認創建的。請注意,已支持的特性不再支持Java 9,而上面的系統屬性只有在$catalinahome/背書存在時才會設置,或者已經設置了可變的javaendorseddirs。

注意,覆蓋任何JRE組件都有風險。如果覆蓋的組件不提供100%兼容的API(例如Xerces提供的API與JRE提供的XML API不兼容),那么Tomcat和/或部署的應用程序將會出現錯誤的風險。

4.在安全模式下運行

當在安全管理器下運行時,允許加載類的位置也將取決于您的策略文件的內容。由于內容較長,將在后續的文章介紹。

點擊查看更多內容

本文原創發布于慕課網 ,轉載請注明出處,謝謝合作

8人點贊

若覺得本文不錯,就分享一下吧!

評論

相關文章推薦

正在加載中
意見反饋 幫助中心 APP下載
官方微信

舉報

0/150
提交
取消
lpl竞猜