Tomcat源码解析三(Tomcat启动过程解析)

Tomcat初始化以及启动流程图:

 

在BootStrap的main方法中调用Bootstrap的start()方法

1. Bootstrap#start()方法实现

public void start()
        throws Exception {
        if( catalinaDaemon==null ) init();
        /**
         * 调用{@link Catalina#start()}
         */
        Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
        method.invoke(catalinaDaemon, (Object [])null);
    }

分析: 在Bootstrap#start()方法中利用反射执行Catalina的start()方法

2. Catalina#start()方法实现

   /**
     * 开启一个新的Server实例
     */
    public void start() {

        if (getServer() == null) {
            load();
        }

        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }

        long t1 = System.nanoTime();

        // Start the new server
        try {
            /**
             * 1. 启动Server
             * {@link StandardServer#startInternal()}
             * 从此处开始, 在父组件中初始化子组件, 一层一层嵌套启动
             */
            getServer().start();
        } catch (LifecycleException e) {
            log.fatal(sm.getString("catalina.serverStartFail"), e);
            try {
                getServer().destroy();
            } catch (LifecycleException e1) {
                log.debug("destroy() failed for failed Server ", e1);
            }
            return;
        }
        //计算并记录启动所用时间
        long t2 = System.nanoTime();
        if(log.isInfoEnabled()) {
            log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
        }

        /**
         * 2. 注册关闭钩子
         * “关闭钩子”其实就是一个线程,JVM 在停止之前会尝试执行这个线程的 run 方法
         *  shutdownHook实际上就执行了 Server 的 stop 方法,Server 的 stop 方法会释放和清理所有的资源
         */
        if (useShutdownHook) {
            if (shutdownHook == null) {
                shutdownHook = new CatalinaShutdownHook();
            }
            Runtime.getRuntime().addShutdownHook(shutdownHook);

            // If JULI is being used, disable JULI's shutdown hook since
            // shutdown hooks run in parallel and log messages may be lost
            // if JULI's hook completes before the CatalinaShutdownHook()
            LogManager logManager = LogManager.getLogManager();
            if (logManager instanceof ClassLoaderLogManager) {
                ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                        false);
            }
        }

        if (await) {
            await();
            stop();
        }
    }

分析: 

  1.  启动Server组件
  2.  注册关闭钩子; “关闭钩子” 其实就是一个线程,JVM 在停止之前会尝试执行这个线程的 run 方法 * shutdownHook实际上就执行了 Server 的 stop 方法,Server 的 stop 方法会释放和清理所有的资源

2.1 创建关闭钩子线程

protected class CatalinaShutdownHook extends Thread {

        @Override
        public void run() {
            try {
                if (getServer() != null) {
                    //调用Catalina的stop方法,关闭资源
                    Catalina.this.stop();
                }
            } catch (Throwable ex) {
                ExceptionUtils.handleThrowable(ex);
                log.error(sm.getString("catalina.shutdownHookFail"), ex);
            } finally {
                // If JULI is used, shut JULI down *after* the server shuts down
                // so log messages aren't lost
                LogManager logManager = LogManager.getLogManager();
                if (logManager instanceof ClassLoaderLogManager) {
                    ((ClassLoaderLogManager) logManager).shutdown();
                }
            }
        }
    }

 2.2 启动Server组件

LifecycleBase#star()方法实现:

@Override
    public final synchronized void start() throws LifecycleException {

        if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {

            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
            }

            return;
        }

        if (state.equals(LifecycleState.NEW)) {
            init();
        } else if (state.equals(LifecycleState.FAILED)) {
            stop();
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }

        try {
            //触发STARTING_PREP事件的监听器
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
            //由子类实现
            startInternal();

            if (state.equals(LifecycleState.FAILED)) {
                // This is a 'controlled' failure. The component put itself into the
                // FAILED state so call stop() to complete the clean-up.
                stop();
            } else if (!state.equals(LifecycleState.STARTING)) {
                // Shouldn't be necessary but acts as a check that sub-classes are
                // doing what they are supposed to.
                invalidTransition(Lifecycle.AFTER_START_EVENT);
            } else {
                //触发STARTED事件的监听器
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        } catch (Throwable t) {
            // This is an 'uncontrolled' failure so put the component into the
            // FAILED state and throw an exception.
            handleSubClassException(t, "lifecycleBase.startFail", toString());
        }
    }

分析:

  1. 状态校验, 如果server处于NEW状态, 则调用init()方法; 如果出现异常,则调用stop()方法;
  2. 触发STARTING_PREP事件的监听器
  3. 子类实现 (模板方法模式)
  4. 触发STARTED事件的监听器

StandardServer#startInternal()方法实现

    @Override
    protected void startInternal() throws LifecycleException {

        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);

        globalNamingResources.start();

        // Start our defined Services
        synchronized (servicesLock) {
            for (int i = 0; i < services.length; i++) {
                /**
                 * 启动Service
                 * {@link StandardService#startInternal()}
                 */
                services[i].start();
            }
        }
    }

分析:

  1. 生命状态的设置
  2. 启动Service; services数组存储该server中的Service组件对象, 数组默认为空, 每添加一个service, 都需要对数组进行扩容

StandardServer#addService()方法实现:

    @Override
    public void addService(Service service) {
        //给service设置server父组件
        service.setServer(this);

        synchronized (servicesLock) {
            /**
             * 创建一个长度+1的新数组
             *
             * 并没有一开始就分配一个很长的数组,而是在添加的过程中动态地扩展数组长度,
             * 当添加一个新的 Service 实例时,会创建一个新数组并把原来数组内容复制到新数组,
             * 这样做的目的其实是为了节省内存空间
             */
            Service results[] = new Service[services.length + 1];
            //将老的数据复制过去
            System.arraycopy(services, 0, results, 0, services.length);
            results[services.length] = service;
            services = results;
            //启动Service组件
            if (getState().isAvailable()) {
                try {
                    service.start();
                } catch (LifecycleException e) {
                    // Ignore
                }
            }

            //触发监听事件
            // Report this property change to interested listeners
            support.firePropertyChange("service", null, service);
        }

    }

StandardService#startInternal方法实现:

@Override
    protected void startInternal() throws LifecycleException {

        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));
        setState(LifecycleState.STARTING);

        // Start our defined Container first
        if (engine != null) {
            synchronized (engine) {
                /**
                 * 启动引擎(容器)
                 * {@link StandardEngine#startInternal()}
                 */
                engine.start();
            }
        }

        synchronized (executors) {
            for (Executor executor: executors) {
                //启动Executor
                executor.start();
            }
        }

        mapperListener.start();

        // Start our defined Connectors second
        synchronized (connectorsLock) {
            for (Connector connector: connectors) {
                try {
                    // If it has already failed, don't try and start it
                    if (connector.getState() != LifecycleState.FAILED) {
                        /**
                         * 启动Connector
                         * {@link Connector#startInternal()}
                         */
                        connector.start();
                    }
                } catch (Exception e) {
                    log.error(sm.getString(
                            "standardService.connector.startFailed",
                            connector), e);
                }
            }
        }
    }

分析:

  1. 启动引擎(容器)
  2. 启动Executor
  3. mapperListener监听器启动
  4. 启动Connector(连接器)

 

相关文章:

      Tomcat源码解析一(Tomcat整体架构解析)

      Tomcat源码解析二(Tomcat初始化过程解析)

      Tomcat源码解析三(Tomcat启动过程解析)

      Tomcat源码解析四(连接器启动过程解析)

      Tomcat源码解析五(容器的启动过程解析)

      Tomcat源码解析六(Http请求过程解析_基于NIO)

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值