在上一章查看tomcat启动文件都干点啥---catalina.bat,说了在catalina.bat中都走了什么流程,最重要的是,我们得出了如下这段命令:
_EXECJAVA=start "Tomcat" "E:\Program Files\Java\jdk1.7.0_40\bin\java" JAVA_OPTS= -Djava.util.logging.config.file="F:\apache-tomcat-7.0.8\conf\logging.properties" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager CATALINA_OPTS= DEBUG_OPTS= -Djava.endorsed.dirs="F:\apache-tomcat-7.0.8\endorsed" -classpath "F:\apache-tomcat-7.0.8\bin\bootstrap.jar;F:\apache-tomcat-7.0.8\bin\tomcat-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\temp" 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 completed Bootstrap 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 reporting if (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 completed Bootstrap 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 path setCatalinaHome(); setCatalinaBase(); initClassLoaders(); Thread.currentThread().setContextClassLoader(catalinaLoader); SecurityClassLoad.securityClassLoad(catalinaLoader); // Load our startup class and call its process() method if (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 loader if (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变量。
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索bootstrap
, command
, 方法
, args
, daemon
, catalina.bat
daemon启动
,以便于您获取更多的相关知识。