Tomcat 啟動流程與類加載機制
1. 引言
Tomcat 的啟動不僅僅是簡單的 java -jar
或 catalina.sh start
。
它背后包含 Bootstrap 啟動器、Catalina 控制器、Server/Service/Connector/Container 初始化 等關鍵步驟。
另一方面,Tomcat 為了支持 熱部署、不同應用間類隔離,設計了 破壞雙親委派機制的類加載模型,這是 Java Web 容器的核心機制。
本篇我們將從 啟動流程 和 類加載機制 兩方面,全面剖析 Tomcat 內核。
2. Tomcat 啟動流程總覽
Tomcat 的啟動過程主要分為以下幾個階段:
-
Bootstrap 初始化
- 加載
catalina.properties
- 初始化 Tomcat 的類加載器體系
- 加載
-
Catalina 初始化
- 創建
Catalina
對象 - 解析
server.xml
配置文件
- 創建
-
Server 與 Service 構建
- 創建
StandardServer
- 創建
StandardService
,并綁定 Connector 與 Container
- 創建
-
啟動 Server
- 調用
server.start()
- 啟動 Service → 啟動 Connector(協議監聽) & Container(加載 Web 應用)
- 調用
👉 流程圖:
Bootstrap↓
Catalina↓
Server (StandardServer)↓
Service (StandardService)↓
Connector + Container↓
應用可對外提供服務
3. 啟動入口:Bootstrap
Tomcat 的入口類是 org.apache.catalina.startup.Bootstrap
:
public final class Bootstrap {public static void main(String[] args) {Bootstrap bootstrap = new Bootstrap();bootstrap.init();bootstrap.start();}
}
主要步驟:
-
init()
- 加載系統屬性、解析配置文件
- 創建類加載器:
CatalinaClassLoader
-
start()
- 反射調用
org.apache.catalina.startup.Catalina
的load()
方法 - Catalina 進一步加載
server.xml
并初始化 Server
- 反射調用
4. Catalina 控制器
org.apache.catalina.startup.Catalina
是 Tomcat 的 核心控制器,負責解析配置文件并啟動 Server:
public void load() {Digester digester = createStartDigester(); // XML 解析器InputSource inputSource = getConfigFile("server.xml");digester.parse(inputSource); // 解析 server.xmlserver = (Server) digester.getRoot();
}
- 使用 Digester(基于 SAX 的 XML 解析器)解析
server.xml
- 創建 Server → Service → Connector/Container 的對象模型
- 保存到內存,供后續啟動調用
5. Server 與 Service 初始化
Tomcat 的核心組件是通過 server.xml
配置加載的:
<Server port="8005" shutdown="SHUTDOWN"><Service name="Catalina"><Connector port="8080" protocol="HTTP/1.1"/><Engine name="Catalina" defaultHost="localhost"><Host name="localhost" appBase="webapps"/></Engine></Service>
</Server>
- Server:代表整個 Tomcat 實例
- Service:將 Connector 和 Container 組合
- Connector:監聽端口、接收請求
- Container:四層容器體系(Engine → Host → Context → Wrapper)
6. Server 啟動流程
當調用 server.start()
時:
- Server.start() → 啟動所有 Service
- Service.start() → 啟動 Connector 和 Container
- Connector.start() → 打開端口,開始監聽 HTTP/AJP 請求
- Container.start() → 加載 Web 應用,初始化 Servlet
源碼片段:
public class StandardServer extends LifecycleBase {@Overrideprotected void startInternal() throws LifecycleException {for (Service service : services) {service.start(); // 啟動 Service}}
}
7. Tomcat 的類加載機制
普通 Java 程序的類加載遵循 雙親委派機制:
BootstrapClassLoader↓
ExtClassLoader↓
AppClassLoader↓
用戶自定義類加載器
但是 Tomcat 必須滿足:
- 不同 Web 應用類相互隔離
- 公共類(如 Servlet API)在所有應用共享
- 支持熱部署、重新加載
因此 Tomcat 打破了雙親委派,設計了 多層類加載器模型。
8. Tomcat 類加載器體系
Tomcat 的類加載器層次:
- Bootstrap ClassLoader(JVM 內置,加載
rt.jar
等) - System ClassLoader(AppClassLoader)
- CommonClassLoader(加載
$CATALINA_HOME/lib
) - CatalinaClassLoader(加載 Tomcat 自身核心類)
- SharedClassLoader(應用共享類)
- WebAppClassLoader(應用私有類,加載
WEB-INF/classes
和WEB-INF/lib
)
👉 層次關系圖:
BootstrapClassLoader↓
SystemClassLoader↓
CommonClassLoader├── CatalinaClassLoader (Tomcat 內部類)├── SharedClassLoader (共享庫)└── WebAppClassLoader (應用隔離)
9. 破壞雙親委派的實現
Tomcat 的 WebAppClassLoaderBase
重寫了 loadClass
方法:
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {// 1. 先從緩存中找Class<?> clazz = findLoadedClass(name);if (clazz == null) {try {// 2. 先自己嘗試加載clazz = findClass(name);} catch (ClassNotFoundException e) {// 3. 加載不到再交給父加載器clazz = super.loadClass(name, resolve);}}return clazz;
}
區別:
- 普通類加載器:先父后子(雙親委派)
- Tomcat WebAppClassLoader:先子后父(保證 Web 應用的私有類優先加載)
10. 類加載機制的應用場景
- Servlet API:在
CommonClassLoader
中加載,供所有應用共享 - 第三方依賴(例如 Spring Jar 包):放在
WEB-INF/lib
,由 WebAppClassLoader 加載,避免沖突 - 熱部署:通過銷毀并重建 WebAppClassLoader 實現
11. 總結
在本篇中,我們詳細剖析了:
-
啟動流程
- Bootstrap 初始化 → Catalina 控制器 → Server/Service → Connector/Container
-
類加載機制
- 普通雙親委派 vs Tomcat 類加載模型
- WebAppClassLoader 打破雙親委派,保證應用隔離
-
應用價值
- 支持多應用隔離
- 支持熱部署
- 保證公共 API 的統一性