Tomcat 启动流程与类加载机制

在这里插入图片描述

1. 引言

Tomcat 的启动不仅仅是简单的 java -jarcatalina.sh start
它背后包含 Bootstrap 启动器、Catalina 控制器、Server/Service/Connector/Container 初始化 等关键步骤。

另一方面,Tomcat 为了支持 热部署、不同应用间类隔离,设计了 破坏双亲委派机制的类加载模型,这是 Java Web 容器的核心机制。

本篇我们将从 启动流程类加载机制 两方面,全面剖析 Tomcat 内核。


2. Tomcat 启动流程总览

Tomcat 的启动过程主要分为以下几个阶段:

  1. Bootstrap 初始化

    • 加载 catalina.properties
    • 初始化 Tomcat 的类加载器体系
  2. Catalina 初始化

    • 创建 Catalina 对象
    • 解析 server.xml 配置文件
  3. Server 与 Service 构建

    • 创建 StandardServer
    • 创建 StandardService,并绑定 Connector 与 Container
  4. 启动 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();
    }
}

主要步骤:

  1. init()

    • 加载系统属性、解析配置文件
    • 创建类加载器:CatalinaClassLoader
  2. start()

    • 反射调用 org.apache.catalina.startup.Catalinaload() 方法
    • 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.xml
    server = (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() 时:

  1. Server.start() → 启动所有 Service
  2. Service.start() → 启动 Connector 和 Container
  3. Connector.start() → 打开端口,开始监听 HTTP/AJP 请求
  4. Container.start() → 加载 Web 应用,初始化 Servlet

源码片段:

public class StandardServer extends LifecycleBase {
    @Override
    protected 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 的类加载器层次:

  1. Bootstrap ClassLoader(JVM 内置,加载 rt.jar 等)
  2. System ClassLoader(AppClassLoader)
  3. CommonClassLoader(加载 $CATALINA_HOME/lib
  4. CatalinaClassLoader(加载 Tomcat 自身核心类)
  5. SharedClassLoader(应用共享类)
  6. WebAppClassLoader(应用私有类,加载 WEB-INF/classesWEB-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. 总结

在本篇中,我们详细剖析了:

  1. 启动流程

    • Bootstrap 初始化 → Catalina 控制器 → Server/Service → Connector/Container
  2. 类加载机制

    • 普通双亲委派 vs Tomcat 类加载模型
    • WebAppClassLoader 打破双亲委派,保证应用隔离
  3. 应用价值

    • 支持多应用隔离
    • 支持热部署
    • 保证公共 API 的统一性

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐