服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

云服务器|WEB服务器|FTP服务器|邮件服务器|虚拟主机|服务器安全|DNS服务器|服务器知识|Nginx|IIS|Tomcat|

服务器之家 - 服务器技术 - Tomcat - Tomcat启动核心流程示例详解

Tomcat启动核心流程示例详解

2022-08-20 10:15请叫我黄同学 Tomcat

这篇文章主要为大家介绍了Tomcat启动核心流程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、Tomcat启动核心流程

前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核心组件,比如Server,Service肯定都绕不开生命周期的方法。

Tomcat启动核心流程示例详解

 

1.启动的入口

你可以通过脚本来启动Tomcat服务(startup.bat),但如果你看过脚本的命令,你会发现最终调用的还是Bootstrap中的main方法,所以我们需要从main方法来开始

Tomcat启动核心流程示例详解

然后我们去看main方法中的代码,我们需要重点关注的方法有三个

  • bootstrap.init()方法
  • load()方法
  • start()方法

也就是在这三个方法中会完成Tomcat的核心操作。

 

2.init方法

我们来看下init方法中的代码,非核心的我们直接去掉

    public void init() throws Exception {
        // 创建相关的类加载器
        initClassLoaders();
        // 省略部分代码...
        // 通过反射创建了 Catalina 类对象
        Class<?> startupClass = catalinaLoader
            .loadClass("org.apache.catalina.startup.Catalina");
        // 创建了 Catalina 实例
        Object startupInstance = startupClass.getConstructor().newInstance();
        // 省略部分代码...
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        // 把 sharedLoader 设置为了 commonLoader的父加载器
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);
        // Catalina 实例 赋值给了 catalinaDaemon
        catalinaDaemon = startupInstance;
    }
  • 首先是调用了initClassLoaders()方法,这个方法会完成对应的ClassLoader的创建,这个比较重要,后面专门写一篇文章来介绍。
  • 通过反射的方式创建了Catalina的类对象,并通过反射创建了Catalina的实例
  • 设置了类加载器的父子关系
  • 用过成员变量catalinaDaemon记录了我们创建的Catalina实例

这个是通过bootstrap.init()方法我们可以获取到的有用的信息。然后我们继续往下面看。

 

3.load方法

然后我们来看下load方法做了什么事情,代码如下:

    private void load(String[] arguments) throws Exception {
        // Call the load() method
        String methodName = "load"; // load方法的名称
        Object param[];
        Class<?> paramTypes[];
        if (arguments==null || arguments.length==0) {
            paramTypes = null;
            param = null;
        } else {
            paramTypes = new Class[1];
            paramTypes[0] = arguments.getClass();
            param = new Object[1];
            param[0] = arguments;
        }
        // catalinaDaemon 就是在 init中创建的 Catalina 对象
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled()) {
            log.debug("Calling startup class " + method);
        }
        // 会执行 Catalina的load方法
        method.invoke(catalinaDaemon, param);
    }

上面的代码非常简单,通过注释我们也可以看出该方法的作用是调用 Catalina的load方法。所以我们还需要加入到Catalina的load方法中来查看,代码同样比较长,只留下关键代码

    public void load() {
        if (loaded) {
            return; // 只能被加载一次
        }
        loaded = true;
        initDirs(); // 废弃的方法
        // Before digester - it may be needed
        initNaming(); // 和JNDI 相关的内容 忽略
        // Create and execute our Digester
        // 创建并且执行我们的 Digester 对象  Server.xml
        Digester digester = createStartDigester();
        // 省略掉了 Digester文件处理的代码
        getServer().setCatalina(this); // Server对象绑定 Catalina对象
        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
        // Stream redirection
        initStreams();
        // 省略掉了部分代码...
         getServer().init(); // 完成 Server  Service Engine Connector等组件的init操作
    }

把上面的代码简化后我们发现这个Load方法其实也是蛮简单的,就做了两件事。

  • 通过Apache下的Digester组件完成了Server.xml文件的解析
  • 通过getServer().init() 方法完成了Server,Service,Engin,Connector等核心组件的初始化操作,这块和前面的LifecycleBase呼应起来了。

Tomcat启动核心流程示例详解

如果生命周期的内容不清楚,请看前面内容介绍

 

4.start方法

最后我们来看下start方法的代码。

    public void start() throws Exception {
        if (catalinaDaemon == null) {
            init(); // 如果 catalinaDaemon 为空 初始化操作
        }
        // 获取的是 Catalina 中的 start方法
        Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
        // 执行 Catalina 的start方法
        method.invoke(catalinaDaemon, (Object [])null);
    }

上面的代码逻辑也很清楚,就是通过反射的方式调用了Catalina对象的start方法。所以进入Catalina的start方法中查看。

    public void start() {
        if (getServer() == null) {
            load(); // 如果Server 为空 重新 init 相关的组件
        }
        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }
        // Start the new server  关键方法---&gt;启动Server
        try {
            getServer().start();
        } catch (LifecycleException e) {
            // 省略...
        }
        // 省略...
        // Register shutdown hook  注册关闭的钩子
        if (useShutdownHook) {
            // 省略...
        }
        if (await) {
            await();
            stop();
        }
    }

通过上面的代码我们可以发现核心的代码还是getServer.start()方法,也就是通过Server对象来嵌套的调用相关注解的start方法。

Tomcat启动核心流程示例详解

 

5.核心流程的总结

我们可以通过下图来总结下Tomcat启动的核心流程

Tomcat启动核心流程示例详解

从图中我们可以看到Bootstrap其实没有做什么核心的事情,主要还是Catalina来完成的。

以上就是Tomcat启动核心流程示例详解的详细内容,更多关于Tomcat启动流程的资料请关注服务器之家其它相关文章!

原文地址:https://juejin.cn/post/7132710433475002405

延伸 · 阅读

精彩推荐
  • TomcatTomcat配置gzip压缩提高浏览网站的速度

    Tomcat配置gzip压缩提高浏览网站的速度

    HTTP 压缩可以大大提高浏览网站的速度,相对于普通的浏览过程HTML ,CSS,Javascript , Text ,它可以节省40%左右的流量...

    Tomcat教程网9812021-08-06
  • TomcatTomcat常见异常及解决方案代码实例

    Tomcat常见异常及解决方案代码实例

    这篇文章主要介绍了Tomcat常见异常及解决方案代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可...

    Erneste6342021-09-12
  • Tomcat详解Tomcat Web 应用绑定域名的几种方式

    详解Tomcat Web 应用绑定域名的几种方式

    本篇文章主要介绍了详解Tomcat Web 应用绑定域名的几种方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Wray Zheng4382021-08-27
  • TomcatTomcat启动失败的问题排查与解决

    Tomcat启动失败的问题排查与解决

    最近在工作中遇到一个问题,在发布失败的机器上Tomcat一直没有启动成功,所以只能想办法排查解决,下面这篇文章就介绍了在Tomcat启动时可能遇到的问题...

    Sel-fish13072021-08-19
  • Tomcat图解Linux下安装Tomcat服务器

    图解Linux下安装Tomcat服务器

    这篇文章主要以图文结合的方式为大家详细介绍了Linux下安装Tomcat服务器的详细过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    谙忆5682021-08-13
  • TomcatTomcat修正JDK原生线程池bug的实现原理

    Tomcat修正JDK原生线程池bug的实现原理

    这篇文章主要介绍了Tomcat是如何修正JDK原生线程池bug的,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...

    JavaEdge.11762021-09-27
  • TomcatTomcat 5.5 数据库连接池配置

    Tomcat 5.5 数据库连接池配置

    我用的数据库是MySQL5.5,所以首先要把MySQL的JDBC驱动程序拷贝到Tomcat安装目录的/common/lib下和你自己网站的/WEB-INF/lib下。...

    Tomcat教程网8452021-08-06
  • Tomcateclipse配置Tomcat找不到server选项的解决办法

    eclipse配置Tomcat找不到server选项的解决办法

    这篇文章通过图文并茂的形式给大家介绍eclipse配置Tomcat找不到server选项的解决办法,感兴趣的朋友跟随脚本之家小编一起学习吧...

    彭国正正正11292021-08-31