文章目錄
- 1、前言
- 2、標準的雙親委派模型
- 3、Tomcat的類加載器架構
- 4、Tomcat打破雙親委派模型的方式
- 5、總結
1、前言
雙親委派模型
是一種類加載機制,它確保了類加載器層次結構中的父加載器先于子加載器嘗試加載類。這種機制有助于防止類的重復加載和類之間的不兼容。
然而,為了支持Web應用程序的獨立性和隔離性
,Tomcat需要在某些情況下打破這一原則。
2、標準的雙親委派模型
在標準的雙親委派模型中,類加載器按以下順序嘗試加載類:
- Bootstrap ClassLoader:引導類加載器,負責加載Java核心類庫($JAVA_HOME/jre/lib)。
- Extension ClassLoader:擴展類加載器,負責加載Java擴展庫($JAVA_HOME/jre/lib/ext)。
- Application ClassLoader:應用類加載器,負責加載應用程序的類路徑(classpath)上的類。
子類加載器在加載類時,先請求父加載器加載,只有當父加載器找不到時,子類加載器才會嘗試自己加載。
3、Tomcat的類加載器架構
Tomcat為了支持多個Web應用程序的獨立性,設計了一套復雜的類加載器架構,主要包括以下幾個類加載器:
- Bootstrap ClassLoader:加載JVM核心類。
- System ClassLoader:加載Tomcat自身的類和庫(位于$CATALINA_HOME/lib)。
- Common ClassLoader:加載共享庫(位于$CATALINA_HOME/lib)。
- Webapp ClassLoader:每個Web應用都有自己的類加載器,負責加載Web應用程序的類和庫(位于WEB-INF/classes和WEB-INF/lib)。
4、Tomcat打破雙親委派模型的方式
Tomcat通過
自定義類加載器
的實現,允許Web應用程序在加載類時打破雙親委派模型。這種機制允許Web應用程序優先加載自己的類和庫,而不是依賴父加載器。這種行為主要通過WebappClassLoader
來實現。
具體實現:
WebappClassLoader:Tomcat為每個Web應用創建一個WebappClassLoader實例。這個類加載器會首先嘗試從WEB-INF/classes和WEB-INF/lib中加載類,而不是先委派給父加載器。
雙親委派的打破:
當WebappClassLoader加載類時,它會檢查是否在其自己的類路徑中存在。如果存在,它會直接加載,而不是委派給父加載器。
這種機制通過在WebappClassLoader的loadClass方法中覆蓋默認的雙親委派行為實現。
例如:org.apache.catalina.loader.WebappClassLoaderBase類中的findClass方法實現了優先從Web應用程序的類路徑加載類。
示例代碼:
以下是WebappClassLoader如何打破雙親委派模型的簡化示例:
public class WebappClassLoader extends URLClassLoader {private ClassLoader parent;public WebappClassLoader(URL[] urls, ClassLoader parent) {super(urls, null); // 將父加載器設置為nullthis.parent = parent;}@Overridepublic Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {// 首先,檢查是否已經加載了類Class<?> clazz = findLoadedClass(name);if (clazz == null) {try {// 嘗試從Web應用的類路徑中加載類clazz = findClass(name);} catch (ClassNotFoundException e) {// 如果找不到,再委派給父加載器加載clazz = parent.loadClass(name);}}if (resolve) {resolveClass(clazz);}return clazz;}
}
在這個示例中,WebappClassLoader首先嘗試通過findClass方法加載類,如果找不到再委派給父加載器。這種方式打破了雙親委派模型,使得Web應用程序可以優先加載自己的類。
5、總結
Tomcat通過自定義的WebappClassLoader打破了雙親委派模型,允許Web應用程序優先加載自己的類和資源。這種機制確保了每個Web應用程序的獨立性和隔離性,避免了類庫沖突,并使得每個應用程序可以擁有自己的類和庫版本。