面试官:既然启动流程不太了解,那你知道Tomcat的生命周期是什么样子的么?

简介: 上一次的文章中,阿粉在面试官面前说了对启动流程不太理解,然后和他聊了一会,然后他又提出了你既然不是特别了解启动流程的话,那你对Tomcat的生命周期熟悉么?

序言

Tomcat的生命周期管理的话,我们不能总是从书中获取那些知识,而是结合实践,然后综合书中的内容,进行一层一层的深入分析,这样对自己记忆和理解都能更加的透彻。

启动的时候的

大家可以随便找一个zip版本的Tomcat,然后直接启动起来,我们来看看是个什么样子的,

一月 11, 2021 10:16:24 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["http-bio-8080"]
一月 11, 2021 10:16:24 上午 org.apache.coyote.AbstractProtocol init
信息: Initializing ProtocolHandler ["ajp-bio-8009"]
一月 11, 2021 10:16:24 上午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 470 ms
一月 11, 2021 10:16:24 上午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
一月 11, 2021 10:16:24 上午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/7.0.88
一月 11, 2021 10:16:24 上午 org.apache.catalina.startup.HostConfig deployDirectory

大家看到这个启动过程之后,在联想一下之前的文章中的Tomcat的启动流程,是不是又感觉有点那个味道了,load,然后start,最后然后stop了。

划重点1:Lifecycle

在之前的文章中,我们提到了Lifecycle, 而Tomcat也就是通过Lifecycle接口统一管理生命周期,所有有生命周期的组件都要实现Lifecycle接口,以便提供一致的机制去启动和停止组件。

那么我们就来分析一下这个Lifecycle接口里面都包含了哪些内容,大家可以直接去tomcat的包中的catalina的jar下面去寻找看一下,

  • 定义了13个String类型的变量
  • 定义了3个管理监听器的方法
  • 定义了4个生命周期
  • 定义了2个获取当前状态的方法

那么我们先说这个13个变量:

String BEFORE_INIT_EVENT = "before_init";
    String AFTER_INIT_EVENT = "after_init";
    String START_EVENT = "start";
    String BEFORE_START_EVENT = "before_start";
    String AFTER_START_EVENT = "after_start";
    String STOP_EVENT = "stop";
    String BEFORE_STOP_EVENT = "before_stop";
    String AFTER_STOP_EVENT = "after_stop";
    String AFTER_DESTROY_EVENT = "after_destroy";
    String BEFORE_DESTROY_EVENT = "before_destroy";
    String PERIODIC_EVENT = "periodic";
    String CONFIGURE_START_EVENT = "configure_start";
    String CONFIGURE_STOP_EVENT = "configure_stop";

这13个变量是什么意思呢?在《Tomcat架构解析》一书中说到,这些常量信息用于LifecycleEvent事件的type属性中,作用是区分组件发出的LifecycleEvent事件时的状态(如初始化前、启动前、启动中等)。这种设计方法可以让多种状态都发送同一种类型的时间,然后用其中的一个属性类区分状态而不用定义多种事件。

其实大家可以根据变量的名字就能看出来,初始化前,初始化后,启动,启动前,启动后。。。。说的在直白一点 ,就是为了表示组件发出时的状态而已。

而三个管理监听的方法又是什么呢?

void addLifecycleListener(LifecycleListener var1);
LifecycleListener[] findLifecycleListeners();
void removeLifecycleListener(LifecycleListener var1);

而这个三个监听器也分别就是用来添加,查找和删除LifecycleListener类型的监听器。这里面是三个接口,具体实现一会我们去子类里面找,在这里先知道有这么个东西就行,下面就会直接分析。

4个生命周期

这个就肯定很简单了,比如像我们都知道在Servlet的生命周期一样,init,start,stop,destroy,初始化,启动,停止,销毁,

void init() throws LifecycleException;
void start() throws LifecycleException;
void stop() throws LifecycleException;
void destroy() throws LifecycleException;

2个获取状态的方法

LifecycleState getState();
String getStateName();

毕竟这个Lifecycle是一个接口,它并不是具体的实现类,我们想要了解这个,那么就一定得去具体的实现类里面去找寻这个内容,那么他的实现类是什么呢?来了来了,它来了,LifecycleBase

LifecycleBase

LifecycleBase是抽象类,是tomcat中所有组件类的基类,他实现了Lifecycle,但是Tomcat下的很多子类也同样的继承了它,所以他也是非常重要的,

public abstract class LifecycleBase implements Lifecycle {
 private LifecycleSupport lifecycle = new LifecycleSupport(this);
 // 源组件的当前状态,不同状态触发不同事件
    private volatile LifecycleState state;
    public LifecycleBase() {
        this.state = LifecycleState.NEW;
    }
   }

在这里我们还要注意一下这个LifecycleSupport类,LifecycleSupport中定义了一个LifecycleListener数组类型的属性来保存所有的监听器,然后在里面分别定义了添加,删除,查找,执行监听器的方法,不信的话,我们来看看,毕竟这个类放在这里先new出来也是有一定道理的。

public final class LifecycleSupport {
    private Lifecycle lifecycle = null;
    private LifecycleListener[] listeners = new LifecycleListener[0];
    private final Object listenersLock = new Object();
    public LifecycleSupport(Lifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }
    public void addLifecycleListener(LifecycleListener listener) {
        Object var2 = this.listenersLock;
        synchronized(this.listenersLock) {
            LifecycleListener[] results = new LifecycleListener[this.listeners.length + 1];
            for(int i = 0; i < this.listeners.length; ++i) {
                results[i] = this.listeners[i];
            }
            results[this.listeners.length] = listener;
            this.listeners = results;
        }
    }
    public LifecycleListener[] findLifecycleListeners() {
        return this.listeners;
    }
    public void fireLifecycleEvent(String type, Object data) {
        LifecycleEvent event = new LifecycleEvent(this.lifecycle, type, data);
        LifecycleListener[] interested = this.listeners;
        for(int i = 0; i < interested.length; ++i) {
            interested[i].lifecycleEvent(event);
        }
    }
    public void removeLifecycleListener(LifecycleListener listener) {
        Object var2 = this.listenersLock;
        synchronized(this.listenersLock) {
            int n = -1;
            for(int i = 0; i < this.listeners.length; ++i) {
                if (this.listeners[i] == listener) {
                    n = i;
                    break;
                }
            }
            if (n >= 0) {
                LifecycleListener[] results = new LifecycleListener[this.listeners.length - 1];
                int j = 0;
                for(int i = 0; i < this.listeners.length; ++i) {
                    if (i != n) {
                        results[j++] = this.listeners[i];
                    }
                }
                this.listeners = results;
            }
        }
    }
}

话不多说,我们继续往下,它的生命周期方法又是什么呢?这才是今天的重点。之前我们就说生命周期包含了哪些内容,从init开始,然后start,然后stop以及最后的destroy方法,在实现类里面表现的那是淋漓尽致。

init方法

public final synchronized void init() throws LifecycleException {
        //这里表示只有NEW状态下是可以使用的,
        if (!this.state.equals(LifecycleState.NEW)) {
            this.invalidTransition("before_init");
        }
    //在这里通过不同的状态,然后去触发不同的事件,
        try {
            //设置生命周期状态为INITIALIZING
            this.setStateInternal(LifecycleState.INITIALIZING, (Object)null, false);
            //执行方法
            this.initInternal();
            //设置生命周期状态为INITIALIZED
            this.setStateInternal(LifecycleState.INITIALIZED, (Object)null, false);
        } catch (Throwable var2) {
            ExceptionUtils.handleThrowable(var2);
            this.setStateInternal(LifecycleState.FAILED, (Object)null, false);
            throw new LifecycleException(sm.getString("lifecycleBase.initFail", new Object[]{this.toString()}), var2);
        }
    }

start方法

public final synchronized void start() throws LifecycleException {
    //在这里验证生命周期状态,状态是这三种状态的是为不可用状态STARTING_PREP,STARTING,STARTED
        if (!LifecycleState.STARTING_PREP.equals(this.state) && !LifecycleState.STARTING.equals(this.state) && !LifecycleState.STARTED.equals(this.state)) {
            //如果是NEW状态,执行init方法
            if (this.state.equals(LifecycleState.NEW)) {
                this.init();
            //如果是FAILED状态,那么执行stop方法
            } else if (this.state.equals(LifecycleState.FAILED)) {
                this.stop();
            //如果是INITIALIZED状态,那么就会告诉你是个非法的操作
            } else if (!this.state.equals(LifecycleState.INITIALIZED) && !this.state.equals(LifecycleState.STOPPED)) {
                this.invalidTransition("before_start");
            }
            try {
                //设置启动状态为 STARTING_PREP
                this.setStateInternal(LifecycleState.STARTING_PREP, (Object)null, false);
                this.startInternal();
                //这里就非常的严谨,他会在启动之后,继续去看状态是什么,保证启动成功
                if (this.state.equals(LifecycleState.FAILED)) {
                    this.stop();
                } else if (!this.state.equals(LifecycleState.STARTING)) {
                    this.invalidTransition("after_start");
                } else {
                    this.setStateInternal(LifecycleState.STARTED, (Object)null, false);
                }
            } catch (Throwable var2) {
                ExceptionUtils.handleThrowable(var2);
                this.setStateInternal(LifecycleState.FAILED, (Object)null, false);
                throw new LifecycleException(sm.getString("lifecycleBase.startFail", new Object[]{this.toString()}), var2);
            }
        } else {
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted", new Object[]{this.toString()}), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStarted", new Object[]{this.toString()}));
            }
        }
    }

stop方法

public final synchronized void stop() throws LifecycleException {
        //同样的,和上面一样,三种状态下不可执行
        if (!LifecycleState.STOPPING_PREP.equals(this.state) && !LifecycleState.STOPPING.equals(this.state) && !LifecycleState.STOPPED.equals(this.state)) {
            //如果是NEW状态,状态直接修改为STOPPED
            if (this.state.equals(LifecycleState.NEW)) {
                this.state = LifecycleState.STOPPED;
            } else {
                //如果不是这2中状态,那么就直接异常
                if (!this.state.equals(LifecycleState.STARTED) && !this.state.equals(LifecycleState.FAILED)) {
                    this.invalidTransition("before_stop");
                }
                try {
                    if (this.state.equals(LifecycleState.FAILED)) {
                        this.fireLifecycleEvent("before_stop", (Object)null);
                    } else {
                        this.setStateInternal(LifecycleState.STOPPING_PREP, (Object)null, false);
                    }
                    this.stopInternal();
                    if (!this.state.equals(LifecycleState.STOPPING) && !this.state.equals(LifecycleState.FAILED)) {
                        this.invalidTransition("after_stop");
                    }
                    this.setStateInternal(LifecycleState.STOPPED, (Object)null, false);
                } catch (Throwable var5) {
                    ...
                } finally {
                   ...
                }
            }
        } else {
            ...
        }
    }

destroy方法

public final synchronized void destroy() throws LifecycleException {
        //如果状态是启动失败的,也就是FAILED,那么会直接去调用stop方法,
        if (LifecycleState.FAILED.equals(this.state)) {
            try {
                this.stop();
            } catch (LifecycleException var3) {
                log.warn(sm.getString("lifecycleBase.destroyStopFail", new Object[]{this.toString()}), var3);
            }
        }
        //如果是这两种状态DESTROYING、DESTROYED,那么就不再进行执行了,直接进行return
        if (!LifecycleState.DESTROYING.equals(this.state) && !LifecycleState.DESTROYED.equals(this.state)) {
            if (!this.state.equals(LifecycleState.STOPPED) && !this.state.equals(LifecycleState.FAILED) && !this.state.equals(LifecycleState.NEW) && !this.state.equals(LifecycleState.INITIALIZED)) {
                this.invalidTransition("before_destroy");
            }
            try {
                this.setStateInternal(LifecycleState.DESTROYING, (Object)null, false);
                this.destroyInternal();
                this.setStateInternal(LifecycleState.DESTROYED, (Object)null, false);
            } catch (Throwable var2) {
                ExceptionUtils.handleThrowable(var2);
                this.setStateInternal(LifecycleState.FAILED, (Object)null, false);
                throw new LifecycleException(sm.getString("lifecycleBase.destroyFail", new Object[]{this.toString()}), var2);
            }
        } else {
         ...
    }

阿粉在其中精简了一些代码,如果大家有兴趣的可以自己去翻一下源码,然后自己去看一下,这样对比出来才有效果。

总结

其实就是通过不同的状态转变,然后相应的去调用init、start、stop、destroy方法,然后提供所有Tomcat组件的生命周期管理。

122.jpg

上图就是接口状态不同情况执行不同方法的图,图片来自《Tomcat架构解析》

文献参考

《深入剖析Tomcat》 《Tomcat架构解析》 《Servlet/JSP深入详解》

相关文章
|
7月前
|
网络协议 安全 Java
逆袭!裸辞26天,历经4面,60w“跳”进鹅厂(附面试流程和真题)
在互联网做了几年之后,去大厂“镀镀金”是大部分人的首选。大厂不仅待遇高、福利好,更重要的是,它是对你专业能力的背书,大厂工作背景多少会给你的简历增加几分竞争力。
|
11天前
|
ARouter IDE 开发工具
Android面试题之App的启动流程和启动速度优化
App启动流程概括: 当用户点击App图标,Launcher通过Binder IPC请求system_server启动Activity。system_server指示Zygote fork新进程,接着App进程向system_server申请启动Activity。经过Binder通信,Activity创建并回调生命周期方法。启动状态分为冷启动、温启动和热启动,其中冷启动耗时最长。优化技巧包括异步初始化、避免主线程I/O、类加载优化和简化布局。
28 3
Android面试题之App的启动流程和启动速度优化
|
3天前
|
安全 网络协议 算法
Android网络基础面试题之HTTPS的工作流程和原理
HTTPS简述 HTTPS基于TCP 443端口,通过CA证书确保服务器身份,使用DH算法协商对称密钥进行加密通信。流程包括TCP握手、证书验证(公钥解密,哈希对比)和数据加密传输(随机数加密,预主密钥,对称加密)。特点是安全但慢,易受特定攻击,且依赖可信的CA。每次请求可能复用Session ID以减少握手。
13 2
|
11天前
|
Java 应用服务中间件 API
Tomcat处理一个HTTP请求的执行流程的详细解析
Tomcat处理一个HTTP请求的执行流程的详细解析
18 4
|
16天前
|
Android开发
Android面试题之activity启动流程
该文探讨了Android应用启动和Activity管理服务(AMS)的工作原理。从Launcher启动应用开始,涉及Binder机制、AMS回调、进程创建、Application和Activity的生命周期。文中详细阐述了AMS处理流程,包括创建ClassLoader、加载APK、启动Activity的步骤,以及权限校验和启动模式判断。此外,还补充了activity启动流程中AMS的部分细节。欲了解更多内容,可关注公众号“AntDream”。
16 1
|
17天前
|
Java Linux Android开发
Android面试题之说说系统的启动流程(总结)
这篇文章概述了Android系统的启动流程,从Boot Rom到Zygote进程和SystemServer的启动。init进程作为用户级别的第一个进程,负责创建文件目录、初始化服务并启动Zygote。Zygote通过预加载资源和创建Socket服务,使用fork函数生成SystemServer进程。fork过程中,子进程继承父进程大部分信息但具有独立的进程ID。Zygote预加载资源以减少后续进程的启动时间,而SystemServer启动众多服务并最终开启Launcher应用。文中还讨论了为何从Zygote而非init或SystemServer fork新进程的原因。
24 2
|
16天前
|
vr&ar 数据库 Android开发
Android面试题之ActivityManagerService的启动流程
本文探讨了Android系统的SystemServer启动过程,包括创建SystemContext、引导服务、启动各类核心服务以及AMS的启动和初始化。AMS负责管理activity、广播队列、provider等,并设置SystemProcess,安装系统Provider。当AMS调用SystemReady时,系统UI准备启动,启动Launcher。文中还对比了init、zygote和system_server进程的角色。最后推荐了两本关于Android内核剖析的书籍:柯元旦教授的《Android内核剖析》和罗升阳的《Android系统源代码情景分析》。关注公众号AntDream获取更多内容。
15 0
|
1月前
|
机器学习/深度学习 数据采集 自然语言处理
2024年Python最新【python开发】并发编程(下),2024年最新字节跳动的面试流程
2024年Python最新【python开发】并发编程(下),2024年最新字节跳动的面试流程
2024年Python最新【python开发】并发编程(下),2024年最新字节跳动的面试流程
|
1月前
|
Python
2024年最新【Python】变量 的定义和使用,阿里巴巴蚂蚁金服面试流程
2024年最新【Python】变量 的定义和使用,阿里巴巴蚂蚁金服面试流程
2024年最新【Python】变量 的定义和使用,阿里巴巴蚂蚁金服面试流程
|
1月前
|
调度
【面试问题】说说线程的生命周期?
【1月更文挑战第27天】【面试问题】说说线程的生命周期?