Tomcat - 启动过程:初始化和启动流程

Bootstrap主入口?

Tomcat源码就从它的main方法开始。Tomcat的main方法在org.apache.catalina.startup.Bootstrap 里。 如下代码我们就是创建一个 Bootstrap 对象,调用它的 init 方法初始化,然后根据启动参数,分别调用 Bootstrap 对象的不同方法。

php 复制代码
    /**
     * Main method and entry point when starting Tomcat via the provided scripts.
     *
     * @param args Command line arguments to be processed
     */
    public static void main(String[] args) {
//        创建一个Bootstrap对象,调用它的init方法初始化
        synchronized (daemonLock) {
            if (daemon == null) {
                // Don't set daemon until init() has completed
                Bootstrap bootstrap = new Bootstrap();
                try {
                    bootstrap.init();
                } catch (Throwable t) {
                    handleThrowable(t);
                    log.error("Init exception", t);
                    return;
                }
                daemon = bootstrap;
            } else {
                // When running as a service the call to stop will be on a new
                // thread so make sure the correct class loader is used to
                // prevent a range of class not found exceptions.
                Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
            }
        }

//        根据启动参数,分别调用BootStrap对象的不同方法
        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            switch (command) {
                case "startd":
                    args[args.length - 1] = "start";
                    daemon.load(args);
                    daemon.start();
                    break;
                case "stopd":
                    args[args.length - 1] = "stop";
                    daemon.stop();
                    break;
                case "start":
                    daemon.setAwait(true);
                    daemon.load(args);
                    daemon.start();
                    if (null == daemon.getServer()) {
                        System.exit(1);
                    }
                    break;
                case "stop":
                    daemon.stopServer(args);
                    break;
                case "configtest":
                    daemon.load(args);
                    if (null == daemon.getServer()) {
                        System.exit(1);
                    }
                    System.exit(0);
                    break;
                default:
                    log.warn("Bootstrap: command "" + command + "" does not exist.");
                    break;
            }
        } catch (Throwable t) {
            // Unwrap the Exception for clearer error reporting
            Throwable throwable = t;
            if (throwable instanceof InvocationTargetException && throwable.getCause() != null) {
                throwable = throwable.getCause();
            }
            handleThrowable(throwable);
            log.error("Error running command", throwable);
            System.exit(1);
        }
    }

Catalina是如何初始化的

ini 复制代码
 /**
     * Initialize daemon.
     * 初始化守护进程
     *
     * @throws Exception Fatal initialization error
     */
    public void init() throws Exception {

//        初始化classloader(包括catalinaLoader)
        initClassLoaders();

//        设置当前的线程的contextClassLoader为catalinaLoader
        Thread.currentThread().setContextClassLoader(catalinaLoader);

        // 通过catalinaLoader加载Catalina,并初始化startupInstance 对象
        // Load our startup class and call its process() method
        if (log.isTraceEnabled()) {
            log.trace("Loading startup class");
        }
        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.getConstructor().newInstance();

        // 通过反射调用了setParentClassLoader 方法
        // Set the shared extensions class loader
        if (log.isTraceEnabled()) {
            log.trace("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;
    }
相关推荐
Victor35610 小时前
https://editor.csdn.net/md/?articleId=139321571&spm=1011.2415.3001.9698
后端
Victor35610 小时前
Hibernate(89)如何在压力测试中使用Hibernate?
后端
灰子学技术12 小时前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
Gogo81613 小时前
BigInt 与 Number 的爱恨情仇,为何大佬都劝你“能用 Number 就别用 BigInt”?
后端
fuquxiaoguang13 小时前
深入浅出:使用MDC构建SpringBoot全链路请求追踪系统
java·spring boot·后端·调用链分析
毕设源码_廖学姐14 小时前
计算机毕业设计springboot招聘系统网站 基于SpringBoot的在线人才对接平台 SpringBoot驱动的智能求职与招聘服务网
spring boot·后端·课程设计
野犬寒鸦15 小时前
从零起步学习并发编程 || 第六章:ReentrantLock与synchronized 的辨析及运用
java·服务器·数据库·后端·学习·算法
逍遥德16 小时前
如何学编程之01.理论篇.如何通过阅读代码来提高自己的编程能力?
前端·后端·程序人生·重构·软件构建·代码规范
MX_935916 小时前
Spring的bean工厂后处理器和Bean后处理器
java·后端·spring
程序员泠零澪回家种桔子17 小时前
Spring AI框架全方位详解
java·人工智能·后端·spring·ai·架构