Welcome 微信登录

首页 / 软件开发 / JAVA / 查看tomcat启动文件都干点啥:Bootstrap.java

查看tomcat启动文件都干点啥:Bootstrap.java2014-08-26在上一章查看tomcat启动文件都干点啥---catalina.bat,说了在catalina.bat中都走了什么流程,最重要的是,我们得出了如下这段命令:

_EXECJAVA=start "Tomcat" "E:Program FilesJavajdk1.7.0_40injava" 
JAVA_OPTS= -Djava.util.logging.config.file="F:apache-tomcat-7.0.8conflogging.properties"
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
CATALINA_OPTS=
DEBUG_OPTS=
-Djava.endorsed.dirs="F:apache-tomcat-7.0.8endorsed"
-classpath "F:apache-tomcat-7.0.8inootstrap.jar;F:apache-tomcat-7.0.8in omcat-juli.jar"
-Dcatalina.base="F:apache-tomcat-7.0.8"
-Dcatalina.home="F:apache-tomcat-7.0.8"
-Djava.io.tmpdir="F:apache-tomcat-7.0.8 emp"
MAINCLASS=org.apache.catalina.startup.Bootstrap
CMD_LINE_ARGS= ACTION=start
其中很重要的一个属性是:MAINCLASS=org.apache.catalina.startup.Bootstrap,Bootstrap在bootstrap.jar中,我们看一下Bootstrap的类图:

从每个变量和方法的名字的字面上也能大概看出来变量或者方法的作用。

很显然,程序走到Bootstrap的时候首先调用main方法,main方法是通过脚本启动tomcat的入口,我们看一下main方法中实现的内容:

if (daemon == null) {// Don"t set daemon until init() has completedBootstrap bootstrap = new Bootstrap();try {bootstrap.init();} catch (Throwable t) {handleThrowable(t);t.printStackTrace();return;}daemon = bootstrap;} else {// When running as a service the call to stop will be on a new// thread so make sure the correct class loader is used to prevent// a range of class not found exceptions.Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);}try {String command = "start";if (args.length > 0) {command = args[args.length - 1];}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);} else {log.warn("Bootstrap: command "" + command + "" does not exist.");}} catch (Throwable t) {// Unwrap the Exception for clearer error reportingif (t instanceof InvocationTargetException &&t.getCause() != null) {t = t.getCause();}handleThrowable(t);t.printStackTrace();System.exit(1);}
可以看出main方法主要实现了两个功能:

(1)初始化一个守护进程变量。

(2)加载参数,解析命令,并执行。

下面是初始化守护进程的执行过程:

if (daemon == null) {// Don"t set daemon until init() has completedBootstrap bootstrap = new Bootstrap();try {bootstrap.init();} catch (Throwable t) {handleThrowable(t);t.printStackTrace();return;}daemon = bootstrap;} else {// When running as a service the call to stop will be on a new// thread so make sure the correct class loader is used to prevent// a range of class not found exceptions.Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);}
可以看到在bootstrap.init()方法中对bootstrap变量进行初始化,然后将结果返回给daemon。下面看一下init方法中的实现:

public void init()throws Exception{// Set Catalina pathsetCatalinaHome();setCatalinaBase();initClassLoaders();Thread.currentThread().setContextClassLoader(catalinaLoader);SecurityClassLoad.securityClassLoad(catalinaLoader);// Load our startup class and call its process() methodif (log.isDebugEnabled())log.debug("Loading startup class");Class<?> startupClass =catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");Object startupInstance = startupClass.newInstance();// Set the shared extensions class loaderif (log.isDebugEnabled())log.debug("Setting startup class properties");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);catalinaDaemon = startupInstance;}
init方法中对classLoader进行了初始化,设置了引用的catalinaDaemon变量。