首页 > 代码库 > 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 }
- 对环境变量的读取,主要是读取 catalina.home\catalina.base
- 初始化类加载器,默认使用当前类的类加载器 this.getClass().getClassLoader();
- 加载了Catalina类 classLoader.loadClass("org.apache.catalina.startup.Catalina")
- 反射设置父类加载器 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 }
- 这个方法并没有具体的深入研究,不过从字面意义上来看,应该是设置了一个锁.欢迎各位指正.
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 }
通过反射调用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 }
- #initDirs()完成了读取环境变量
- #initNaming()设置命名空间catalina.useNaming\java.naming.factory.url.pkgs\java.naming.factory.initial 这几个命名空间没有具体研究作用,同样欢迎补充
- 创建Digester
- 读取server.xml文件
- #digester.push(this)
- #digester.parse(inputSource)使用digester解析server.xml并按照配置创建Server对象
- #initStreams()设置log
- 调用#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 }
通过反射调用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 }
- 逐步启动server的生命周期
Tomcat6源码解析--Bootstrap
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。