Tomcat 8 源码学习二之初始化classloader
Contents
Main函数启动
源码org.apache.catalina.startup.Bootstrap这个是启动类,main函数就在这个类中.
第一件事,就是调用Bootstrap.init()方法,我们来看看这个方法做了什么处理.
首先初始化它的静态块代码,设置
catalina.home,catalina.base等相应的环境变量.调用
initClassLoaders()将
Tomcat当前主线程的ContextClassLoader设置为catalinaLoader将
SecurityClassLoader设置为catalinaLoader通过
catalinaLoader.loadClass来加载org.apache.catalina.startup.Catalina类并实例化一个该对象为startupInstance然后,通过反射来设置
startupInstance对象的setParentClassLoader方法来设置它的parent classloader为sharedLoader.最后,将
catalinaDaemon的值,设置为startupInstance.
Tomcat的properties管理类 CatalinaProperties
在进入classloader初始化之前,我们来看看Tomcat加载properties的管理类,就是org.apache.catalina.startup.CatalinaProperties类.
Tomcat加载不同的classLoader,是通过String value = CatalinaProperties.getProperty(name + ".loader");这个配置来加载类的.
而CatalinaProperties类,通过源码可知,它是加载tomcat目录下的conf/catalina.properties文件的.
initClassLoaders() 方法
private void initClassLoaders() {
try {
commonLoader = createClassLoader("common", null);
if( commonLoader == null ) {
// no config file, default to this loader - we might be in a 'single' env.
commonLoader=this.getClass().getClassLoader();
}
catalinaLoader = createClassLoader("server", commonLoader);
sharedLoader = createClassLoader("shared", commonLoader);
} catch (Throwable t) {
handleThrowable(t);
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}
可以看到该方法初始化了三个classloder,分别是commonLoader, catalinaLoader, sharedLoader.而且commonLoader是catalinaLoader和sharedLoader的父classloader.
commonLoader
所以,我们看看这个配置文件中common.loader的value可知是如下:
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
在这里,可以看到,Tomcat是单目录,多实例结构的。catalina.base是实例的目录位置,catalina.home是tomcat安装目录的位置.但一般情况下,我们的catalina.base与catalina.home是相同的.
所以,可以知道commonLoader负载加载上面指定的"${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"这些类的.
根据这样子的情况,我们可以知道,如果想让一个依赖包,让所有的应用都加载的话,可以将这些依赖包,放到以上指定的目录中即可.(不过,一般情况下也不建议这样子做,一个Tomcat中多个应用要加载不同版本的jar包,这样子就会出问题了)
catalinaLoader
可以看到,该loader的父loader是commonLoader.所以通过catalinaLoader加载的类,都会让commonLoader先尝试加载。
该loader加载的是server.loader=这个配置指定的路径的.可以看到,默认情况下它是空的。
sharedLoader
可以看到,该loader的父loader是commonLoader.所以通过sharedLoader加载的类,都会让commonLoader先尝试加载。
该loader加载的是shared.loader=这个配置指定的路径的.可以看到,默认情况下它是空的