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

栏目: Java · 发布时间: 8年前

内容简介:Tomcat 7 启动分析(二)Bootstrap 类中的 main 方法

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

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

1	/**
     2	     * Main method and entry point when starting Tomcat via the provided
     3	     * scripts.
     4	     *
     5	     * @param args Command line arguments to be processed
     6	     */
     7	    public static void main(String args[]) {
     8	
     9	        if (daemon == null) {
    10	            // Don't set daemon until init() has completed
    11	            Bootstrap bootstrap = new Bootstrap();
    12	            try {
    13	                bootstrap.init();
    14	            } catch (Throwable t) {
    15	                handleThrowable(t);
    16	                t.printStackTrace();
    17	                return;
    18	            }
    19	            daemon = bootstrap;
    20	        } else {
    21	            // When running as a service the call to stop will be on a new
    22	            // thread so make sure the correct class loader is used to prevent
    23	            // a range of class not found exceptions.
    24	            Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
    25	        }
    26	
    27	        try {
    28	            String command = "start";
    29	            if (args.length > 0) {
    30	                command = args[args.length - 1];
    31	            }
    32	
    33	            if (command.equals("startd")) {
    34	                args[args.length - 1] = "start";
    35	                daemon.load(args);
    36	                daemon.start();
    37	            } else if (command.equals("stopd")) {
    38	                args[args.length - 1] = "stop";
    39	                daemon.stop();
    40	            } else if (command.equals("start")) {
    41	                daemon.setAwait(true);
    42	                daemon.load(args);
    43	                daemon.start();
    44	            } else if (command.equals("stop")) {
    45	                daemon.stopServer(args);
    46	            } else if (command.equals("configtest")) {
    47	                daemon.load(args);
    48	                if (null==daemon.getServer()) {
    49	                    System.exit(1);
    50	                }
    51	                System.exit(0);
    52	            } else {
    53	                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
    54	            }
    55	        } catch (Throwable t) {
    56	            // Unwrap the Exception for clearer error reporting
    57	            if (t instanceof InvocationTargetException &&
    58	                    t.getCause() != null) {
    59	                t = t.getCause();
    60	            }
    61	            handleThrowable(t);
    62	            t.printStackTrace();
    63	            System.exit(1);
    64	        }
    65	
    66	    }

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

1	/**
     2	     * Initialize daemon.
     3	     */
     4	    public void init()
     5	        throws Exception
     6	    {
     7	
     8	        // Set Catalina path
     9	        setCatalinaHome();
    10	        setCatalinaBase();
    11	
    12	        initClassLoaders();
    13	
    14	        Thread.currentThread().setContextClassLoader(catalinaLoader);
    15	
    16	        SecurityClassLoad.securityClassLoad(catalinaLoader);
    17	
    18	        // Load our startup class and call its process() method
    19	        if (log.isDebugEnabled())
    20	            log.debug("Loading startup class");
    21	        Class<?> startupClass =
    22	            catalinaLoader.loadClass
    23	            ("org.apache.catalina.startup.Catalina");
    24	        Object startupInstance = startupClass.newInstance();
    25	
    26	        // Set the shared extensions class loader
    27	        if (log.isDebugEnabled())
    28	            log.debug("Setting startup class properties");
    29	        String methodName = "setParentClassLoader";
    30	        Class<?> paramTypes[] = new Class[1];
    31	        paramTypes[0] = Class.forName("java.lang.ClassLoader");
    32	        Object paramValues[] = new Object[1];
    33	        paramValues[0] = sharedLoader;
    34	        Method method =
    35	            startupInstance.getClass().getMethod(methodName, paramTypes);
    36	        method.invoke(startupInstance, paramValues);
    37	
    38	        catalinaDaemon = startupInstance;
    39	
    40	    }

这里不再逐句解释代码的作用,总的来说这个方法主要做了一下几件事:

  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 方法代码如下:

1	    /**
     2	     * Load daemon.
     3	     */
     4	    private void load(String[] arguments)
     5	        throws Exception {
     6	
     7	        // Call the load() method
     8	        String methodName = "load";
     9	        Object param[];
    10	        Class<?> paramTypes[];
    11	        if (arguments==null || arguments.length==0) {
    12	            paramTypes = null;
    13	            param = null;
    14	        } else {
    15	            paramTypes = new Class[1];
    16	            paramTypes[0] = arguments.getClass();
    17	            param = new Object[1];
    18	            param[0] = arguments;
    19	        }
    20	        Method method =
    21	            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
    22	        if (log.isDebugEnabled())
    23	            log.debug("Calling startup class " + method);
    24	        method.invoke(catalinaDaemon, param);
    25	
    26	    }

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

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

1	    /**
     2	     * Start the Catalina daemon.
     3	     */
     4	    public void start()
     5	        throws Exception {
     6	        if( catalinaDaemon==null ) init();
     7	
     8	        Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
     9	        method.invoke(catalinaDaemon, (Object [])null);
    10	
    11	    }

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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Big Java Late Objects

Big Java Late Objects

Horstmann, Cay S. / 2012-2 / 896.00元

The introductory programming course is difficult. Many students fail to succeed or have trouble in the course because they don't understand the material and do not practice programming sufficiently. ......一起来看看 《Big Java Late Objects》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具