拆解Tomcat10: (三) 图解Tomcat的启动过程(二)

简介: 上一篇介绍了如何在Idea中下载并调试最新的Tomcat的源码(已更新到2021.12.8日发布的Tomcat 10.0.14)。如果说Tomcat是一部处理请求的机器,想了解Tomcat是如何处理请求的,首先要了解它的内部结构,本章以Tomcat的启动为起点,开启源码学习之旅。

3.按功能看处理流程

将Bootstrap类按其代码分为三部分:


初始化部分,主要是初始化CATALINA_HOME 和CATALINA_BASE变量;

main方法部分一:创建和初始化daemon和catalinaDaemon、创建三个重要类加载器;

main方法部分二:控制Tomcat的启动与停止。

对应流程图如下:

56.png

2. 初始化CATALINA_HOME 和CATALINA_BASE

首先看一下Bootstrap类,最早会通过一段代码确定CATALINA_HOME 和CATALINA_BASE两个重要值:

private static final File catalinaBaseFile;
private static final File catalinaHomeFile;
private static final Pattern PATH_PATTERN = Pattern.compile("(\"[^\"]*\")|(([^,])*)");
static {
    // Will always be non-null
    String userDir = System.getProperty("user.dir");
    // Home first
    String home = System.getProperty(Constants.CATALINA_HOME_PROP);
    //省略部分代码
    catalinaHomeFile = homeFile;
    System.setProperty(Constants.CATALINA_HOME_PROP, catalinaHomeFile.getPath());
    // Then base
    String base = System.getProperty(Constants.CATALINA_BASE_PROP);
    if (base == null) {
        catalinaBaseFile = catalinaHomeFile;
    } else {
        File baseFile = new File(base);
        try {
            baseFile = baseFile.getCanonicalFile();
        } catch (IOException ioe) {
            baseFile = baseFile.getAbsoluteFile();
        }
        catalinaBaseFile = baseFile;
    }
    System.setProperty(
        Constants.CATALINA_BASE_PROP, catalinaBaseFile.getPath());
}

**CATALINA_HOME:**代表Tomcat安装的根目录,例如/home/tomcat/apache-tomcat-9.0.10或C:\Program Files\apache-tomcat-9.0.10。

**CATALINA_BASE:**表示特定 Tomcat 实例的运行时配置的根。如果您想在一台机器上拥有多个 Tomcat 实例,请使用 CATALINA_BASE 属性。


**默认情况下,CATALINA_HOME 和 CATALINA_BASE 指向同一目录。**如果将属性设置为不同的位置,则 CATALINA_HOME 位置包含静态源,例如 .jar 文件或二进制文件。 CATALINA_BASE 位置包含配置文件、日志文件、部署的应用程序和其他运行时要求。


3. 创建并初始化守护进程daemon和catalinaDaemon

初始化完毕,接着执行的就是main方法,这个方法功能分为两部分:

synchronized (daemonLock) {
    if (daemon == null) {
        // 在初始化完成之前,不要对daemon赋值
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.init();
        } catch (Throwable t) {
            handleThrowable(t);
            t.printStackTrace();
            return;
        }
        daemon = bootstrap;
    } else {
        //当作为服务正在运行时,如果调用停止方法,这将在一个新线程上进行,以确保使用正确的类加载器,防止出现未找到类的异常。
        Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
    }
}

首先创建一个Bootstrap类型的对象,并调用其init()方法进行初始化,直至其初始化完毕,将其赋值给daemon对象。

重点在init方法:

public void init() throws Exception {
    //创建并初始化三个ClassLoader
    initClassLoaders();
    Thread.currentThread().setContextClassLoader(catalinaLoader);
    SecurityClassLoad.securityClassLoad(catalinaLoader);
    // Load our startup class and call its process() method
    if (log.isDebugEnabled()) {
        log.debug("Loading startup class");
    }
    //通过反射方式创建
    Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
    Object startupInstance = startupClass.getConstructor().newInstance();
    // Set the shared extensions class loader
    if (log.isDebugEnabled()) {
        log.debug("Setting startup class properties");
    }
    String methodName = "setParentClassLoader";
    Class<?> paramTypes[] = new Class[1];
    paramTypes[0] = Class.forName("java.lang.ClassLoader");
    Object paramValues[] = new Object[1];
    paramValues[0] = sharedLoader;
    Method method =
        startupInstance.getClass().getMethod(methodName, paramTypes);
    method.invoke(startupInstance, paramValues);
    catalinaDaemon = startupInstance;
}
目录
相关文章
|
2月前
|
人工智能 前端开发 Java
【Tomcat源码分析】启动过程深度解析 (二)
本文深入探讨了Tomcat启动Web应用的过程,重点解析了其加载ServletContextListener及Servlet的机制。文章从Bootstrap反射调用Catalina的start方法开始,逐步介绍了StandardServer、StandardService、StandardEngine、StandardHost、StandardContext和StandardWrapper的启动流程。每个组件通过Lifecycle接口协调启动,子容器逐层启动,直至整个服务器完全启动。此外,还详细分析了Pipeline及其Valve组件的作用,展示了Tomcat内部组件间的协作机制。
【Tomcat源码分析】启动过程深度解析 (二)
|
6月前
|
设计模式 算法 前端开发
Tomcat的源码剖析, 启动过程你会吗?
基于JMX Tomcat会为每个组件进行注册过程,通过Registry管理起来,而Registry是基于JMX来实现的,因此在看组件的init和start过程实际上就是初始化MBean和触发MBean的start方法,会大量看到形如: Registry.getRegistry(null, null).invoke(mbeans, "init", false); Registry.getRegistry(null, null).invoke(mbeans, "start", false); 这样的代码,这实际上就是通过JMX管理各种组件的行为和生命期。
36 0
|
XML 应用服务中间件 数据格式
Tomcat - Tomcat 8.5.55 启动过程源码分析阶段三_start阶段
Tomcat - Tomcat 8.5.55 启动过程源码分析阶段三_start阶段
105 0
|
前端开发 Java 应用服务中间件
Tomcat - Tomcat 8.5.55 启动过程源码分析阶段二_load加载初始化
Tomcat - Tomcat 8.5.55 启动过程源码分析阶段二_load加载初始化
97 0
|
前端开发 Java 应用服务中间件
Tomcat - Tomcat 8.5.55 启动过程源码分析阶段一_init实例化Bootstrap
Tomcat - Tomcat 8.5.55 启动过程源码分析阶段一_init实例化Bootstrap
103 0
|
存储 XML Java
Tomcat启动过程原理详解
Tomcat启动过程原理详解
107 0
|
Java 应用服务中间件 容器
面试官:来说说Tomcat的启动过程是什么样子的(下)
阿粉最近在疯狂的研究各种用的工具里面的源码实现,之前给大家都专门的去扣了一下 JDK 里面自带的exe程序,这次阿粉开始更加无聊,直接开始搞Tomcat。
面试官:来说说Tomcat的启动过程是什么样子的(下)
|
前端开发 Java 应用服务中间件
面试官:来说说Tomcat的启动过程是什么样子的(上)
阿粉最近在疯狂的研究各种用的工具里面的源码实现,之前给大家都专门的去扣了一下 JDK 里面自带的exe程序,这次阿粉开始更加无聊,直接开始搞Tomcat。
面试官:来说说Tomcat的启动过程是什么样子的(上)
|
前端开发 应用服务中间件
拆解Tomcat10: (三) 图解Tomcat的启动过程(三)
上一篇介绍了如何在Idea中下载并调试最新的Tomcat的源码(已更新到2021.12.8日发布的Tomcat 10.0.14)。如果说Tomcat是一部处理请求的机器,想了解Tomcat是如何处理请求的,首先要了解它的内部结构,本章以Tomcat的启动为起点,开启源码学习之旅。
432 0
|
1月前
|
安全 应用服务中间件 网络安全
Tomcat如何配置PFX证书?
【10月更文挑战第2天】Tomcat如何配置PFX证书?
177 7