首页 > 代码库 > Tomcat6源码解析--Bootstrap

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 ms30                 daemon.load(args);31                 // 启动server32                 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() method17         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 loader24         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 needed11 12         initNaming();13 14         // Create and execute our Digester15         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.jar38         // 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 InputSource44                 (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.xml64             inputStream.close();65         } catch (Exception e) {66             log.warn("Catalina.start using "67                                + getConfigFile() + ": " , e);68             return;69         }70 71         // Stream redirection72         initStreams();// 设置log73 74         // Start the new server75         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 server18         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 hook32             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 since39                 // shutdown hooks run in parallel and log messages may be lost40                 // 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 run49             // fine without the shutdown hook.50         }51 52         if (await) {53             await();54             stop();55         }56 57     }
Catalina.start方法
  1. 逐步启动server的生命周期

Tomcat6源码解析--Bootstrap