tomcat阅读第三篇(Bootstrap类代码分析)
分析bootstrap类的方法
首先是静态代码段static{},初始化catalinaHomeFile变量和catalinaBaseFile变量,catalinaHomeFile变量默认是bootstrap.jar文件路径,catalinaBaseFile默认情况下等于catalinaHomeFile,可以通过vm –D参数catalina.home和catalina.base覆盖。
static { //当前工作目录,就是平常cmd启动的tomcat的时候进去的目录 String userDir = System.getProperty("user.dir"); //-D參數Catalina.home String home = System.getProperty(Globals.CATALINA_HOME_PROP); File homeFile = null; if (home != null) { File f = new File(home); try { homeFile = f.getCanonicalFile(); } catch (IOException ioe) { homeFile = f.getAbsoluteFile(); } } //如果未指定默认是user.dir的parent dir路径,不过首先要判断user.dir下有没有bootstrap.jar if (homeFile == null) { File bootstrapJar = new File(userDir, "bootstrap.jar"); if (bootstrapJar.exists()) { File f = new File(userDir, ".."); try { homeFile = f.getCanonicalFile(); } catch (IOException ioe) { homeFile = f.getAbsoluteFile(); } } } //当前工作目录作为catalinahome if (homeFile == null) { File f = new File(userDir); try { homeFile = f.getCanonicalFile(); } catch (IOException ioe) { homeFile = f.getAbsoluteFile(); } } catalinaHomeFile = homeFile; System.setProperty( Globals.CATALINA_HOME_PROP, catalinaHomeFile.getPath()); //如果未指定-Dcatalina.base,默认等于catalina.home String base = System.getProperty(Globals.CATALINA_BASE_PROP); if (base == null) { catalinaBaseFile = catalinaHomeFile; } else { File baseFile = new File(base); try { baseFile = baseFile.getCanonicalFile(); } catch (IOException ioe) { baseFile = baseFile.getAbsoluteFile(); } catalinaBaseFile = baseFile; } System.setProperty( Globals.CATALINA_BASE_PROP, catalinaBaseFile.getPath()); }
其次看几个方法main initClassLoaders init load start stop stopServer setAwait方法
main方法主要逻辑:
实例化Bootstrap,调用Bootstrap init方法,然后根据传入的jvm参数调用不同的方法
............. //调用bootstrap init方法 bootstrap.init(); ......................... //根据main参数不同调用bootstrap相应方法 if (command.equals("startd")) { args[args.length - 1] = "start"; daemon.load(args); daemon.start(); } else if (command.equals("stopd")) { args[args.length - 1] = "stop"; daemon.stop(); } else if (command.equals("start")) { daemon.setAwait(true); daemon.load(args); daemon.start(); } else if (command.equals("stop")) { daemon.stopServer(args); } else if (command.equals("configtest")) { daemon.load(args); if (null==daemon.getServer()) { System.exit(1); } System.exit(0);
Init方法主要逻辑:
Step1.调用initClassLoaders方法
Step2.设置当前线程的类加载器为catalinaLoader
Step3.preload tomcat类(SecurityClassLoad)
Step4.用catalinaLoader反射加载org.apache.catalina.startup.Catalina类并实例化
Step5.调用Catalina类的setParentClassLoader方法,将sharedLoader作为catalinaLoader的ParentClassloader
//初始化commonLoader、catalinaLoader、sharedLoader initClassLoaders(); //设置当前线程classloader Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); .............. //用catalinaLoader加载org.apache.catalina.startup.Catalina类 Class<?> startupClass = catalinaLoader.loadClass ("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance(); ........................... //调用setParentClassLoader方法,设置catalinaLoader的parentclassloader为sharedLoader String methodName = "setParentClassLoader"; Class<?> paramTypes[] = new Class[1]; paramTypes[0] = Class.forName("java.lang.ClassLoader"); Object paramValues[] = new Object[1]; paramValues[0] = sharedLoader; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); ...............................
initClassLoaders方法主要逻辑:
调用createClassLoader方法实例化3个classloader(实例化3个classloader(commonLoader、catalinaLoader、sharedLoader)
createClassLoader方法会读取catalina.properties配置文件的配置实例化相应的classloader
默认情况下三个类加载器都是commonclassloader,如果配置加上后面两项,三个类加载器的父子关系如图
Load方法、Start方法、Stop方法、stopServer方法、setAwait方法:
调用Catalina类的l相应方法
总结:bootstrap主要功能是初始化两个静态变量catalinaHome和catalinaBase以及实例化三个classloader,根据main的参数调用不同的catalina方法。