`
Tyrion
  • 浏览: 260917 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Tomcat7启动分析(二)Bootstrap类中的main方法

阅读更多

之前分析了Tomcat的启动脚本,如果从startup.bat开始启动Tomcat的话会发现最后会调用org.apache.catalina.startup.Bootstrap里的main方法,并且传过来的最后一个命令行参数是start,接下来的启动代码分析就从这里开始。

 

先看下这个main方法的代码:

/**
     * 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[]) {

        if (daemon == null) {
            // Don't set daemon until init() has completed
            Bootstrap bootstrap = new Bootstrap();
            try {
                bootstrap.init();
            } catch (Throwable t) {
                handleThrowable(t);
                t.printStackTrace();
                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);
        }

        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

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

    }

这里的daemon是Bootstrap类中的一个静态成员变量,类型就是Bootstrap,第10行的注释已经说明在调用过init方法之后才会给该变量赋值,初始时将是null,所以首先将实例化一个Bootstrap对象,接着调用init方法,该方法代码如下:

/**
     * Initialize daemon.
     */
    public void init()
        throws Exception
    {

        // Set Catalina path
        setCatalinaHome();
        setCatalinaBase();

        initClassLoaders();

        Thread.currentThread().setContextClassLoader(catalinaLoader);

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled())
            log.debug("Loading startup class");
        Class<?> startupClass =
            catalinaLoader.loadClass
            ("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.newInstance();

        // Set the shared extensions class loader
        if (log.isDebugEnabled())
            log.debug("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;

    }

 这里不再逐句解释代码的作用,总的来说这个方法主要做了一下几件事:1.设置catalina.home、catalina.base系统属性,2.创建commonLoader、catalinaLoader、sharedLoader类加载器(默认情况下这三个类加载器指向同一个对象。建议看看createClassLoader方法,里面做的事情还挺多,比如装载catalina.properties里配置的目录下的文件和jar包,后两个加载器的父加载器都是第一个,最后注册了MBean,可以用于JVM监控该对象),3.实例化一个org.apache.catalina.startup.Catalina对象,并赋值给静态成员catalinaDaemon,以sharedLoader作为入参通过反射调用该对象的setParentClassLoader方法。

 

接下来去命令行最后一个参数,按文章开头所说是start,所以将执行34行到36行的代码,将会执行Bootstrap类中的load、start方法。

 

load方法代码如下:

    /**
     * Load daemon.
     */
    private void load(String[] arguments)
        throws Exception {

        // Call the load() method
        String methodName = "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;
        }
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled())
            log.debug("Calling startup class " + method);
        method.invoke(catalinaDaemon, param);

    }

就是通过反射调用catalinaDaemon对象的load方法,catalinaDaemon对象在上面的init方法中已经实例化过了。

 

start方法与load方法相似,也是通过反射调用catalinaDaemon对象上的start方法:

    /**
     * Start the Catalina daemon.
     */
    public void start()
        throws Exception {
        if( catalinaDaemon==null ) init();

        Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
        method.invoke(catalinaDaemon, (Object [])null);

    }

 

下面一篇文章将分析catalinaDaemon对象中的load、start两个方法,里面会涉及一个有趣的话题——Digester的使用。

1
2
分享到:
评论
9 楼 小帅1127 2017-02-18  
Verson 写道
博主您好,你文章中提到的创建Tomcat类加载器后会跟着注册JMX对象,我看的Tomcat中源码并无此操作,不知是否是Tomcat版本的区别还是我没找到,我用的Tomcat版本是7.0.72

我也有此疑问 我也是没看到此操作
8 楼 Verson 2016-11-01  
博主您好,你文章中提到的创建Tomcat类加载器后会跟着注册JMX对象,我看的Tomcat中源码并无此操作,不知是否是Tomcat版本的区别还是我没找到,我用的Tomcat版本是7.0.72
7 楼 Tyrion 2013-08-22  
Rambing 写道
Tyrion 写道
Rambing 写道
楼主你好最近我也在看tomcat的源代码,希望可以多多交流
下面这个地方感觉表述的不是很准确,【2.创建commonLoader、catalinaLoader、sharedLoader三个类加载器(建议看看createClassLoader方法,里面做的事情还挺多,比如装载catalina.properties里配置的目录下的文件和jar包,后两个加载器的父加载器都是第一个,最后注册了MBean,可以用于JVM监控该对象)】这三个commonLoader、catalinaLoader、sharedLoader这三个类加载器应用的是同一个对象。在tomcat7的官方文档对于类加载器的介绍上已经去掉了catalinaLoader、sharedLoader则两个层级。感觉代码是因为历史原因才保留成当前这个样子的。实际上这两类加载已经被废弃了。

欢迎交流,
commonLoader、catalinaLoader、sharedLoader这三个不是同一个对象,看看里面150行这句:ClassLoader classLoader = ClassLoaderFactory.createClassLoader (repositories, parent);
在ClassLoaderFactory类里最终有这句话:
if (parent == null)
                            return new StandardClassLoader(array);
                        else
                            return new StandardClassLoader(array, parent);
catalinaLoader、sharedLoader最终是会新产生一个加载器对象,但这两个加载器的父加载器都是commonLoader,所以它们默认寻找的类路径是一致的。


应该看前面的代码:
private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {

        String value = CatalinaProperties.getProperty(name + ".loader");
        if ((value == null) || (value.equals("")))
            return parent;

默认情况下因为Value的值是null,这个可以打开“catalina.properties”文件查看。
Tomcat7的文档中【http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html】对于类加载器的描述也改为下面这个结构了。
      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ...



哦,这里我忽略了,默认情况下catalina.properties文件里面只配置了common.loader属性,server.loader和shared.loader属性值是空。
感谢指正
6 楼 Rambing 2013-08-22  
Tyrion 写道
Rambing 写道
楼主你好最近我也在看tomcat的源代码,希望可以多多交流
下面这个地方感觉表述的不是很准确,【2.创建commonLoader、catalinaLoader、sharedLoader三个类加载器(建议看看createClassLoader方法,里面做的事情还挺多,比如装载catalina.properties里配置的目录下的文件和jar包,后两个加载器的父加载器都是第一个,最后注册了MBean,可以用于JVM监控该对象)】这三个commonLoader、catalinaLoader、sharedLoader这三个类加载器应用的是同一个对象。在tomcat7的官方文档对于类加载器的介绍上已经去掉了catalinaLoader、sharedLoader则两个层级。感觉代码是因为历史原因才保留成当前这个样子的。实际上这两类加载已经被废弃了。

欢迎交流,
commonLoader、catalinaLoader、sharedLoader这三个不是同一个对象,看看里面150行这句:ClassLoader classLoader = ClassLoaderFactory.createClassLoader (repositories, parent);
在ClassLoaderFactory类里最终有这句话:
if (parent == null)
                            return new StandardClassLoader(array);
                        else
                            return new StandardClassLoader(array, parent);
catalinaLoader、sharedLoader最终是会新产生一个加载器对象,但这两个加载器的父加载器都是commonLoader,所以它们默认寻找的类路径是一致的。


应该看前面的代码:
private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {

        String value = CatalinaProperties.getProperty(name + ".loader");
        if ((value == null) || (value.equals("")))
            return parent;

默认情况下因为Value的值是null,这个可以打开“catalina.properties”文件查看。
Tomcat7的文档中【http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html】对于类加载器的描述也改为下面这个结构了。
      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ...


5 楼 Tyrion 2013-08-21  
Rambing 写道
楼主你好最近我也在看tomcat的源代码,希望可以多多交流
下面这个地方感觉表述的不是很准确,【2.创建commonLoader、catalinaLoader、sharedLoader三个类加载器(建议看看createClassLoader方法,里面做的事情还挺多,比如装载catalina.properties里配置的目录下的文件和jar包,后两个加载器的父加载器都是第一个,最后注册了MBean,可以用于JVM监控该对象)】这三个commonLoader、catalinaLoader、sharedLoader这三个类加载器应用的是同一个对象。在tomcat7的官方文档对于类加载器的介绍上已经去掉了catalinaLoader、sharedLoader则两个层级。感觉代码是因为历史原因才保留成当前这个样子的。实际上这两类加载已经被废弃了。

欢迎交流,
commonLoader、catalinaLoader、sharedLoader这三个不是同一个对象,看看里面150行这句:ClassLoader classLoader = ClassLoaderFactory.createClassLoader (repositories, parent);
在ClassLoaderFactory类里最终有这句话:
if (parent == null)
                            return new StandardClassLoader(array);
                        else
                            return new StandardClassLoader(array, parent);
catalinaLoader、sharedLoader最终是会新产生一个加载器对象,但这两个加载器的父加载器都是commonLoader,所以它们默认寻找的类路径是一致的。
4 楼 Rambing 2013-08-21  
楼主你好最近我也在看tomcat的源代码,希望可以多多交流
下面这个地方感觉表述的不是很准确,【2.创建commonLoader、catalinaLoader、sharedLoader三个类加载器(建议看看createClassLoader方法,里面做的事情还挺多,比如装载catalina.properties里配置的目录下的文件和jar包,后两个加载器的父加载器都是第一个,最后注册了MBean,可以用于JVM监控该对象)】这三个commonLoader、catalinaLoader、sharedLoader这三个类加载器应用的是同一个对象。在tomcat7的官方文档对于类加载器的介绍上已经去掉了catalinaLoader、sharedLoader则两个层级。感觉代码是因为历史原因才保留成当前这个样子的。实际上这两类加载已经被废弃了。
3 楼 sgq0085 2013-07-23  
helloqiner 写道
顶起!
楼主能否实现一个嵌入式tomcat7的例子?

嵌入式的可以考虑jetty,案例参考springside4就行了
2 楼 Tyrion 2013-07-23  
helloqiner 写道
顶起!
楼主能否实现一个嵌入式tomcat7的例子?

谢谢。
我没做过嵌入式应用,真没看懂“嵌入式tomcat”是什么意思。
1 楼 helloqiner 2013-07-23  
顶起!
楼主能否实现一个嵌入式tomcat7的例子?

相关推荐

    bootstrap开启与关闭tomcat

    Bootstrap是Apache Tomcat服务器的核心启动类,它是Tomcat初始化过程中的关键部分,主要负责加载服务器的配置信息并启动核心服务。在Java应用服务器领域,理解如何通过Bootstrap接口控制Tomcat的启动与关闭对于运维...

    Tomcat启动顺序

    Bootstrap会调用`org.apache.catalina.startup.Bootstrap.main()`方法来启动Tomcat。 2. System类加载器: Bootstrap类加载器完成后,Tomcat会使用系统类加载器(System ClassLoader)加载服务器的全局配置文件,如`...

    Tomcat 6.0启动过程分析

    `Bootstrap` 类作为 Tomcat 的启动入口,承担着构建一个独立的类加载器的任务,用于装载 `Catalina` 的内部类,以此来确保这些内部类与系统的 classpath 相隔离,避免与应用级别的类产生冲突。 - **主函数 main** ...

    tomcat-bootstrap and juli.jar

    当我们在命令行中运行`catalina.sh`或`catalina.bat`启动脚本时,实际上是执行了Bootstrap的main方法。Bootstrap首先会定位并加载`server.xml`配置文件,然后通过Java的反射机制创建并启动Tomcat的核心服务,如引擎...

    Tomcat 6 启动过程分析.doc

    Bootstrap的`main`方法是程序的起点,通过`daemon.init()`初始化Tomcat环境,然后根据命令行参数决定启动或停止Tomcat服务。`initClassLoaders()`方法负责创建三个类加载器:commonLoader、catalinaLoader和...

    我的tomcat7源码手撕过程

    2. **加载Classpath**:在启动脚本中,通过关键字`CLASSPATH`指定`bin\bootstrap.jar`等JAR包的位置,这些JAR包包含了启动Tomcat所需的类和资源。 3. **主类加载**:脚本中通过关键字`MAINCLASS`指定了主类`org....

    Tomcat5启动流程与配置详解 .

    - 加载`$CATALINA_HOME/bin/bootstrap.jar`初始化Tomcat,并执行`Main`方法。 - 加载`$JAVA_HOME/lib/tools.jar`,Sun的工具类,包括编译JSP为Servlet的工具类。 - **Common**: - 这个目录下的类虽然对Tomcat和...

    Tomcat源码分析1

    首先,Tomcat的启动过程始于`startup.bat`或`startup.sh`脚本,这些脚本最终调用`org.apache.catalina.startup.Bootstrap`类的`main`方法。此方法的首要任务是定义和初始化Tomcat的类加载器。类加载器是Java程序中至...

    tomcat-src整理的Eclipse项目

    该文件解压后就是Eclipse项目,可直接导入Eclipse 为我们研究tomcat源码提供了方便,运行org.apache.catalina.startup.Bootstrap类的main方法即可启动tomcat。

    tomcat源码分析

    - `main`方法执行`init`步骤,初始化`CatalinaHome`、`CatlinaBase`以及类加载器。 - `start`方法启动Tomcat服务器。 2. **Catalina类**: - `load`方法中创建并解析`server.xml`配置文件。 - `start`方法继续...

    springboot+bootstrap的管理后台demo

    2. **src/main/java**:包含主程序类、配置类以及业务逻辑处理类,SpringBoot的核心代码通常放在这里。 3. **src/main/resources**:存放配置文件,如application.properties或yml,数据库连接配置、Redis配置等。 4...

    tomcat8:tomcat8源码分析

    在运行Bootstrap的main方法时,将下面代码拷入到vm options 中 -Dcatalina.home=launch -Dcatalina.base=launch -Djava.endorsed.dirs=launch/endorsed -Djava.io.tmpdir=launch/temp -Djava.util.logging.manager=...

    springboot+mybatis+bootstrap项目

    4. 在IDE中,右键点击`Application.java`,选择“Run 'Application.main()'”或者直接在代码中找到`public static void main(String[] args)`方法,按F9运行。 5. 这样,Spring Boot应用就会启动,内嵌的Web服务器会...

    使用JavaServiceWrapper设置tomcat作为linux服务并且开机自动启动.pdf

    ### 使用Java Service Wrapper设置Tomcat作为Linux服务并实现开机自动启动 #### 一、概述 在部署基于Java的应用服务器时,通常需要将Tomcat配置为系统服务,以便于管理和维护。传统的做法是通过编写shell脚本来...

    Tomcat原理解析

    1. **Bootstrap:main(args)** - 启动点,执行main方法。 2. **Catalina:load(args)** - 初始化Catalina核心组件。 3. **StandardServer:initialize()** - 初始化服务器实例。 4. **StandardService:initialize()** -...

    Tomcat的架构和设计

    1. **Bootstrap**:`org.apache.catalina.startup.Bootstrap.main()`方法是Tomcat启动的入口,它加载`Catalina`类,并调用`process()`方法开始启动流程。 2. **读取配置**:在`Catalina.process()`方法中,首先创建...

    apache-tomcat-9.0.54-embed.tar.gz

    总之,Apache Tomcat 9.0.54-embed 是一个强大的工具,它提供了一种简洁的方法来在你的应用程序中集成Java Web服务,便于开发和测试。通过理解和利用其核心功能,你可以创建高效、稳定的Web应用环境。

    JFinal + shiro+freemarker +bootstrap3 后台基础管理

    3.直接add到eclipse中的tomcat,就能启动了 测试后台密码 admin 123456 生产环境发布 1. 修改src/main/resources/production 下的 db.properties为生产环境中的数据库链接 mvn 命令打包 mvn clean package -...

    Tomcat技术培训

    - **启动脚本**:通过`start.sh`脚本启动,该脚本调用Bootstrap的main方法。 - **容器初始化**:`load`方法解析`server.xml`文件,根据配置信息创建容器并设置属性。接着初始化和启动各个容器。 - **监听端口**:`...

    apache tomcat 8.5.34 源码

    apache tomcat 8.5.34 源码 Mark Directory as Sources Root: java/ Main: org.apache.catalina.startup.Bootstrap.main

Global site tag (gtag.js) - Google Analytics