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的生命周期
时间: 2024-10-11 23:22:01

Tomcat6源码解析--Bootstrap的相关文章

Bootstrap 源码解析

Bootstrap 源码解析 1.Bootstrap的作用域 2.Bootstrap的类定义 3.Bootstrap的插件定义 4.Bootstrap的事件代理 5.Bootstrap的对象数据缓存 6.Bootstrap的防冲突 7.作用域外如何使用Button类 8.Bootstrap的单元测试 Bootstrap的作用域 Bootstrap每个插件都定义在下面这段作用域代码中: 请看<IIFE>和<严格模式>编译环境. 在插件的作用域之外,全局范围执行代码的第一行,检测了jQ

Appuim源码剖析(Bootstrap)

Appuim源码剖析(Bootstrap) SkySeraph Jan. 26th 2017 Email:[email protected] 更多精彩请直接访问SkySeraph个人站点:www.skyseraph.com About Appuim Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用. 这里有很关键一点,跨平台.更多了解Appuim多平台支持相关信息,参考官方platform-support 相关概念 C/S 架

normalize.css源码解析

什么是normalize.css?  它是为了帮助我们统一各个浏览器的样式和消除bug的css库. 为什么需要normalize.css,有什么好处? 不像一些reset.css,normalize.css会保持浏览器的默认效果. 对大多数的元素进行了合理的限制. 修复了bug和一些常见的浏览器的不一致. 提高了开发效率. normalize.css使用情况如何? github地址:https://github.com/necolas/normalize.css. 从github上我们可以看到,

Netty5源码解析

Netty5源码解析 今天让我来总结下netty5的服务端代码. 服务端(ServerBootstrap) 示例代码如下: import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel

Laravel源码解析--看看Lumen到底比Laravel轻在哪里

在前面一篇<Laravel源码解析--Laravel生命周期详解>中我们利用xdebug详细了解了下Laravel一次请求中到底做了哪些处理.今天我们跟 Lumen 对比下,看看 Lumen 比 Laravel 轻在哪里? 1.Lumen生命周期 相比于Laravel,在Lumen中,你对框架有着更多的控制权.Lumen的入口文件相比于Laravel要简单许多. <?php /* |-----------------------------------------------------

netty服务端启动--ServerBootstrap源码解析

netty服务端启动--ServerBootstrap源码解析 前面的第一篇文章中,我以spark中的netty客户端的创建为切入点,分析了netty的客户端引导类Bootstrap的参数设置以及启动过程.显然,我们还有另一个重要的部分--服务端的初始化和启动过程没有探究,所以这一节,我们就来从源码层面详细分析一下netty的服务端引导类ServerBootstrap的启动过程. spark中netty服务端的创建 我们仍然以spark中对netty的使用为例,以此为源码分析的切入点,首先我们看

ChrisRenke/DrawerArrowDrawable源码解析

转载请注明出处http://blog.csdn.net/crazy__chen/article/details/46334843 源码下载地址http://download.csdn.net/detail/kangaroo835127729/8765757 这次解析的控件DrawerArrowDrawable是一款侧拉抽屉效果的控件,在很多应用上我们都可以看到(例如知乎),控件的github地址为https://github.com/ChrisRenke/DrawerArrowDrawable

五.jQuery源码解析之jQuery.extend(),jQuery.fn.extend()

给jQuery做过扩展或者制作过jQuery插件的人这两个方法东西可能不陌生.jQuery.extend([deep],target,object1,,object2...[objectN]) jQuery.fn.extend([deep],target,object1,,object2...[objectN])这两个属性都是用于合并两个或多个对象的属性到target对象.deep是布尔值,表示是否进行深度合并,默认是false,不执行深度合并.通过这种方式可以在jQuery或jQuery.fn

eclipse中导入jdk源码、SpringMVC注解@RequestParam、SpringMVC文件上传源码解析、ajax上传excel文件

eclipse中导入jdk源码:http://blog.csdn.net/evolly/article/details/18403321, http://www.codingwhy.com/view/799.html. ------------------------------- SpringMVC注解@RequestParam:http://825635381.iteye.com/blog/2196911. --------------------------- SpringMVC文件上传源