Tomcat是接触最久的应用服务器,同时也被它的classloading愚弄过好多次。印象中比较深的一次是建立了一个web应用,使用oracle数据库,我把oracle的jdbc driver放到了WEB-INF/lib目录下面,然后给Tomcat配置了数据源,在这个应用里面连接这个数据源,来访问数据库。看起来一切正常,可是一启动Tomcat,就报出一个错误,说是找不到driver类。后来知道这是由于Tomcat的classloading机制造成的。总的来说,Tomcat开源、简单,文档清楚,又学习过一阵它的源码,是我了解最多的应用服务器了,所以就从它开始。
BootStrap classloader(加载JRE/lib下的rt.jar和其他重要jar文件) |
é
ExtClassLoader (加载JRE/lib/ext下的jar文件,Java扩展框架使用) |
é
AppClassLoader ($CATALINA_HOME/bin/下bootstrap.jar, commons-logging -api.jar,commons-daemon.jar,$JAVA_HOME/lib/tools.jar,jmx.jar) |
é
common (加载$CATALINA_HOME/common/,Tomcat本身和Web App共享类) |
é é
Catalina (加载$CATALINA_HOME /server/,Tomcat本身使用的类) |
Shared (加载$CATALINA_BASE /shared/,所有Web App共享类) |
é
WebappClassLoader (加载各个Web App的class,不同的Web App被隔离开) |
正是因为这种机制,使我们在两个Web app中有相同的class的时候,不会相互干扰。比如说,两个app中都使用了log4j,在WEB-INF/lib下面分别有一份log4j.jar,配置输出到不同的文件。因为WebappClassLoader仅对本app可见,所以log4j可以独立工作,而不相互影响。但是,如果我们把这两个app下面的log4j.jar移动到shared目录或者common目录,那他们就会把日志输出到同样的文件了,因为这时候是共享的。