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=
这个配置指定的路径的.可以看到,默认情况下它是空的