从catalina.sh中可以看出,tomcat启动的入口和参数配置,下面是执行catalina.sh脚本时,打印出来的详细信息
exec /home/work/local/jdk1.6.0_31/bin/java -Djava.util.logging.config.file=/home/work/local/apache-tomcat-
6.0.35/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -server -Xm
s8000m -Xmx8000m -Xmn6000m -XX:PermSize=128m -XX:MaxPermSize=256m -XX:SurvivorRatio=4 -Xss1024K -verbose:gc
-XX:-DisableExplicitGC -Xloggc:/logs/gc.log -Djava.awt.headless=true -Dfile.encoding=gbk -Dcom.sun.managemen
t.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.mana
gement.jmxremote.authenticate=false -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,add
ress=8764,server=y,suspend=n -Djava.endorsed.dirs=/home/work/local/apache-tomcat-6.0.35/endorsed -classpath
/home/work/local/apache-tomcat-6.0.35/bin/bootstrap.jar -Dcatalina.base=/home/work/local/apache-tomcat-6.0.3
5 -Dcatalina.home=/home/work/local/apache-tomcat-6.0.35 -Djava.io.tmpdir=/home/work/local/apache-tomcat-6.0.
35/temp org.apache.catalina.startup.Bootstrap start
中间部分是参数,简化之后,相当于启动tomcat服务器的命令是
java org.apache.catalina.startup.Bootstrap start
同时设置了几个后续会用到的系统变量如下
catalina.base = /home/work/local/apache-tomcat-6.0.35
catalina.home = /home/work/local/apache-tomcat-6.0.35
在Bootstrap加载时,会通过这两个系统变量来设置其成员变量
private static final File catalinaBaseFile;
private static final File catalinaHomeFile;
这里,它们都指向同一个目录
从Apache Tomcat官网
(https://tomcat.apache.org/tomcat-8.0-doc/architecture/startup.html)上找出服务启动时的时序图如下
对照Bootstrap类的源码进行解析,源码版本(tomcat-catalina-8.0.20)
initClassLoaders()
初始化tomcat服务的classloader,用于后续类的加载。
tomcat有3个classloader:commonLoader、catalinaLoader和sharedLoader。commonLoader是catalinaLoader和sharedLoader的父loader。
commonLoader的名字是common.loader,在配置文件(catalina.properties)中,指向的路径是
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"。最后的效果是,commonLoader加载类时,会从tomcat的lib目录,以及lib目录中的jar文件去寻找。
catalinaLoader和sharedLoader如果没有设置,默认情况下会指向commonLoader,也就是它们三个实际上都指向了同一个ClassLoader对象,从同一个地方去加载类。
newInstance()
加载Catalina类,生成Catalina对象
这里会用到在上一步初始化的catalinaLoader来加载,
Class<?> startupClass =
catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
setParentClassLoader()
设置生成的Catalina对象的父类加载器
Catalina有一个parentClassLoader属性设置为sharedLoader
String methodName = "setParentClassLoader";
paramValues[0] = sharedLoader;
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
load()
为Catalina对象加载配置,启动tomcat服务
通过反射调用Catalina对象的load方法,加载并解析配置文件,启动tomcat服务。
Catalina的load方法中做的操作较多,下面进行分解:
a、调用initDirs和initNaming()做tmp路径和命名的初始化。
b、调用 createStartDigester();生成Digester对象。Digester类负责进行配置文件的解析。
c、加载配置文件(server.xml),获取输入流InputStream对象
d、利用Digester解析配置文件输入流,解析之后,获取配置的root节点表示对象。也就是Server对象。server.xml的根节点就是<server>标签
e、对上一步生成的server对象进行初始化,启动服务