Tomcat6源码解析--Bootstrap

package org.apache.catalina.startup;

src file:http://svn.apache.org/repos/asf/tomcat/tc6.0.x/tags/TOMCAT_6_0_42/java/org/apache/catalina/startup/Bootstrap.java

goal:了解tomcat启动的大致流程

欢迎各位指正其中的错误和不足

入口main方法

 1 public static void main(String args[]) {
 2 
 3         if (daemon == null) {
 4             daemon = new Bootstrap();
 5             try {
 6                 daemon.init();//init(完成了加载环境变量和类加载器的工作)
 7             } catch (Throwable t) {
 8                 t.printStackTrace();
 9                 return;
10             }
11         }
12 
13         try {
14             String command = "start";
15             if (args.length > 0) {
16                 command = args[args.length - 1];
17             }
18 
19             if (command.equals("startd")) {
20                 args[args.length - 1] = "start";
21                 daemon.load(args);
22                 daemon.start();
23             } else if (command.equals("stopd")) {
24                 args[args.length - 1] = "stop";
25                 daemon.stop();
26             } else if (command.equals("start")) {// 默认没有参数会进入这里
27                 // 设置挂起标志
28                 daemon.setAwait(true);
29                 // 信息: Initialization processed in 3024454 ms
30                 daemon.load(args);
31                 // 启动server
32                 daemon.start();
33             } else if (command.equals("stop")) {
34                 daemon.stopServer(args);
35             } else {
36                 log.warn("Bootstrap: command \"" + command + "\" does not exist.");
37             }
38         } catch (Throwable t) {
39             t.printStackTrace();
40         }
41 
42     }

以上是bootstrap类的main方法,里边逐步调用了一些用于初始化的方法.下面一一解读:

init()方法:

 1 /**
 2      * Initialize daemon.
 3      */
 4     public void init() throws Exception {
 5 
 6         // Set Catalina path
 7         setCatalinaHome();// 加载Catalina.Home环境变量(catalina.home)
 8         setCatalinaBase();// 加载Catalina.Base环境变量(catalina.base)
 9 
10         initClassLoaders();// 初始化类加载器
11 
12         Thread.currentThread().setContextClassLoader(catalinaLoader);
13 
14         SecurityClassLoad.securityClassLoad(catalinaLoader);
15 
16         // Load our startup class and call its process() method
17         if (log.isDebugEnabled()) {
18             log.debug("Loading startup class");
19         }
20         Class startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
21         Object startupInstance = startupClass.newInstance();
22 
23         // Set the shared extensions class loader
24         if (log.isDebugEnabled()) {
25             log.debug("Setting startup class properties");
26         }
27         String methodName = "setParentClassLoader";
28         Class paramTypes[] = new Class[1];
29         paramTypes[0] = Class.forName("java.lang.ClassLoader");
30         Object paramValues[] = new Object[1];
31         paramValues[0] = sharedLoader;
32         // 找到org.apache.catalina.startup.Catalina#setParentClassLoader方法
33         Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
34         // 设置java.lang.ClassLoader为父类加载器
35         method.invoke(startupInstance, paramValues);
36 
37         catalinaDaemon = startupInstance;// 设置Catalina进程
38     }
init()方法
  1. 对环境变量的读取,主要是读取  catalina.home\catalina.base
  2. 初始化类加载器,默认使用当前类的类加载器  this.getClass().getClassLoader();
  3. 加载了Catalina类  classLoader.loadClass("org.apache.catalina.startup.Catalina")
  4. 反射设置父类加载器  org.apache.catalina.startup.Catalina#setParentClassLoader设置java.lang.ClassLoader为ParentClassLoader

daemon.setAwait(true)方法:

 1 /**
 2      * Set flag.
 3      */
 4     public void setAwait(boolean await) throws Exception {
 5 
 6         Class paramTypes[] = new Class[1];
 7         paramTypes[0] = Boolean.TYPE;
 8         Object paramValues[] = new Object[1];
 9         paramValues[0] = new Boolean(await);
10         // 获取Catalina类(其实是其父类Embedded)中的setAwait方法
11         Method method = catalinaDaemon.getClass().getMethod("setAwait", paramTypes);
12         // 使用await参数调用
13         method.invoke(catalinaDaemon, paramValues);
14 
15     }
setAwait方法
  1. 这个方法并没有具体的深入研究,不过从字面意义上来看,应该是设置了一个锁.欢迎各位指正.

daemon.load(args)方法:

 1 /**
 2      * Load daemon.
 3      */
 4     private void load(String[] arguments) throws Exception {
 5 
 6         // Call the load() method
 7         String methodName = "load";
 8         Object param[];
 9         Class paramTypes[];
10         if (arguments==null || arguments.length==0) {
11             paramTypes = null;
12             param = null;
13         } else {
14             paramTypes = new Class[1];
15             paramTypes[0] = arguments.getClass();
16             param = new Object[1];
17             param[0] = arguments;
18         }
19         // 获取Catalina的load方法
20         Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes);
21         if (log.isDebugEnabled())
22             log.debug("Calling startup class " + method);
23         // 调用(启动一个新的服务器实例)
24         method.invoke(catalinaDaemon, param);
25 
26     }
daemon.load方法

  通过反射调用Catalina的load方法

 1 /**
 2      * Start a new server instance.
 3      */
 4     public void load() {
 5 
 6         long t1 = System.nanoTime();
 7 
 8         initDirs();// 读取环境变量
 9 
10         // Before digester - it may be needed
11 
12         initNaming();
13 
14         // Create and execute our Digester
15         Digester digester = createStartDigester();
16 
17         InputSource inputSource = null;
18         InputStream inputStream = null;
19         File file = null;
20         try {
21             file = configFile();//获取server.xml位置
22             inputStream = new FileInputStream(file);
23             inputSource = new InputSource("file://" + file.getAbsolutePath());
24         } catch (Exception e) {
25             ;
26         }
27         // 如果不能获取server.xml,则使用ClassLoader再查找一次
28         if (inputStream == null) {
29             try {
30                 inputStream = getClass().getClassLoader().getResourceAsStream(getConfigFile());
31                 inputSource = new InputSource(getClass().getClassLoader().getResource(getConfigFile()).toString());
32             } catch (Exception e) {
33                 ;
34             }
35         }
36 
37         // This should be included in catalina.jar
38         // Alternative: don't bother with xml, just create it manually.
39         if( inputStream==null ) {
40             try {
41                 inputStream = getClass().getClassLoader()
42                 .getResourceAsStream("server-embed.xml");
43                 inputSource = new InputSource
44                 (getClass().getClassLoader()
45                         .getResource("server-embed.xml").toString());
46             } catch (Exception e) {
47                 ;
48             }
49         }
50         
51 
52         if ((inputStream == null) && (file != null)) {
53             log.warn("Can't load server.xml from " + file.getAbsolutePath());
54             if (file.exists() && !file.canRead()) {
55                 log.warn("Permissions incorrect, read permission is not allowed on the file.");
56             }
57             return;
58         }
59 
60         try {
61             inputSource.setByteStream(inputStream);
62             digester.push(this);
63             digester.parse(inputSource);// 加载server.xml
64             inputStream.close();
65         } catch (Exception e) {
66             log.warn("Catalina.start using "
67                                + getConfigFile() + ": " , e);
68             return;
69         }
70 
71         // Stream redirection
72         initStreams();// 设置log
73 
74         // Start the new server
75         if (getServer() instanceof Lifecycle) {
76             try {
77                 getServer().initialize();
78             } catch (LifecycleException e) {
79                 if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
80                     throw new java.lang.Error(e);
81                 else   
82                     log.error("Catalina.start", e);
83                 
84             }
85         }
86 
87         long t2 = System.nanoTime();
88         if(log.isInfoEnabled())
89             log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
90 
91     }
Catalina.load方法
  1. #initDirs()完成了读取环境变量
  2. #initNaming()设置命名空间catalina.useNaming\java.naming.factory.url.pkgs\java.naming.factory.initial  这几个命名空间没有具体研究作用,同样欢迎补充
  3. 创建Digester
  4. 读取server.xml文件
  5. #digester.push(this)
  6. #digester.parse(inputSource)使用digester解析server.xml并按照配置创建Server对象
  7. #initStreams()设置log
  8. 调用#getServer().initialize()启动server

daemon.start()方法:

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

 

  通过反射调用Catalina的start方法

 1 /**
 2      * Start a new server instance.
 3      */
 4     public void start() {
 5 
 6         if (getServer() == null) {
 7             load();
 8         }
 9 
10         if (getServer() == null) {
11             log.fatal("Cannot start server. Server instance is not configured.");
12             return;
13         }
14 
15         long t1 = System.nanoTime();
16         
17         // Start the new server
18         if (getServer() instanceof Lifecycle) {
19             try {
20                 ((Lifecycle) getServer()).start();
21             } catch (LifecycleException e) {
22                 log.error("Catalina.start: ", e);
23             }
24         }
25 
26         long t2 = System.nanoTime();
27         if(log.isInfoEnabled())
28             log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
29 
30         try {
31             // Register shutdown hook
32             if (useShutdownHook) {
33                 if (shutdownHook == null) {
34                     shutdownHook = new CatalinaShutdownHook();
35                 }
36                 Runtime.getRuntime().addShutdownHook(shutdownHook);
37                 
38                 // If JULI is being used, disable JULI's shutdown hook since
39                 // shutdown hooks run in parallel and log messages may be lost
40                 // if JULI's hook completes before the CatalinaShutdownHook()
41                 LogManager logManager = LogManager.getLogManager();
42                 if (logManager instanceof ClassLoaderLogManager) {
43                     ((ClassLoaderLogManager) logManager).setUseShutdownHook(
44                             false);
45                 }
46             }
47         } catch (Throwable t) {
48             // This will fail on JDK 1.2. Ignoring, as Tomcat can run
49             // fine without the shutdown hook.
50         }
51 
52         if (await) {
53             await();
54             stop();
55         }
56 
57     }
Catalina.start方法
  1. 逐步启动server的生命周期

posted on 2014-10-21 18:18  beenoisy  阅读(295)  评论(0编辑  收藏  举报

导航