tomcat 学习 |tomcat 的启动过程

本贴最后更新于 1717 天前,其中的信息可能已经天翻地覆

开头说两句

小刀博客: https://www.lixiang.red
小刀公众号: 程序员学习大本营

学习背景

在前两篇中,我们讲述了 tomcat 的源码结构
https://www.lixiang.red/articles/2019/08/04/1564907616303.html
还有 tomcat 的 server.xml 结构.
https://www.lixiang.red/articles/2019/08/06/1565094623138.html
今天我们来继续看 tomcat 的启动过程

从已知 startup.bat/sh 入手

windows 上启动是:startup.bat
linux/mac 上启动是 startup.sh
image.png

startup.sh

重点在于最后一行:

# PRGDIR 是当前tomcat下的bin目录
PRGDIR=`dirname "$PRG"`

EXECUTABLE=catalina.sh

执行tomcat/bin/catalina.sh start 
$@ 是代表全部的参数,
exec "$PRGDIR"/"$EXECUTABLE" start "$@"

catalina.sh

我们通过参数 start 进行追踪:
image.png
在这里看到了对 start 参数进行判断,然后走不同的分支逻辑
经过一大堆的判断,最后达到可启动的状态时,就开始执行启动的命令:
image.png

nohup: 是 linux 系统中,可以后台运行程序的命令,窗口关掉也会存在

ENDORSED_PROP: 可以覆盖部分 jvm bootstarp 类加载器加载的类

org.apache.catalina.startup.Bootstrap: 最后会执行这个类

Bootstrap

根据上文,我们可以找到 Bootstrap 这个类的 main 函数
image.png
如上图所示,只要执行了以下几步:

  1. 初始化 bootstrap 实例
  2. 调用 bootstrap 的 init 方法,去初始化类加载器,以及 catalina 实例
  3. 调用 bootstrap 的 start 方法,然后通过反射去调用 catalina 的 start 方法

init():

 public void init() throws Exception {
        // 初始化类加载器
        initClassLoaders();
        // 设置当前线程的类加载器为catalinaLoader
        // 当前线程:初始化Catalina的线程,初始化Servlet容器的这个线程
        Thread.currentThread().setContextClassLoader(catalinaLoader);

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled()){
            log.debug("Loading startup class");
        }
        // 寻找到 Catalina 类,然后用反射进行实例化
        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");
        }
        // 获取到Catalina.setParentClassLoader的方法
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        // 通过反射设置 Catalina实例使用的父类加载器为sharedLoader
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

        catalinaDaemon = startupInstance;

    }

start():

public void start()
        throws Exception {
        if( catalinaDaemon==null ) init();
        // 使用反射去调用Catalina 的 start 方法
        Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
        method.invoke(catalinaDaemon, (Object [])null);

    }

最后说两句

这样就完成了 tomcat 从命令行到 bootstrap 以及 catalina 的初步初始化.后面还有 server,service , Engine , host 等组件的加载
在本篇学习中,小伙伴们有什么问题,可以和小刀一起交流: best396975802

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...