tomcat遵循j2ee规范,实现了web容器。很多有关web的书籍和文章都离不开对tomcat的分析,初学者可以从tomcat的实现对j2ee有更深入的了解。此外,tomcat还根据java虚拟机规范实现了经典的双亲委派模式的类加载体系。本文基于tomcat7.0的java源码,对其类加载体系进行分析。
首先简单介绍下java虚拟机规范中提到的主要类加载器;
bootstrap loader:加载lib目录下或者system.getproperty(“sun.boot.class.path”)、或者-xbootclasspath所指定的路径或jar。
extended loader:加载lib\ext目录下或者system.getproperty(“java.ext.dirs”) 所指定的 路径或jar。在使用java运行程序时,也可以指定其搜索路径,例如:java -djava.ext.dirs=d:\projects\testproj\classes helloworld。
appclass loader:加载system.getproperty("java.class.path")所指定的 路径或jar。在使用java运行程序时,也可以加上-cp来覆盖原有的classpath设置,例如: java -cp ./lavasoft/classes helloworld。
然后用一张图片来展示tomcat的类加载体系:
这里对上图所示类加载体系进行介绍:
classloader:java提供的类加载器抽象类,用户自定义的类加载器需要继承实现
commonloader:tomcat最基本的类加载器,加载路径中的class可以被tomcat容器本身以及各个webapp访问;
catalinaloader:tomcat容器私有的类加载器,加载路径中的class对于webapp不可见;
sharedloader:各个webapp共享的类加载器,加载路径中的class对于所有webapp可见,但是对于tomcat容器不可见;
webappclassloader:各个webapp私有的类加载器,加载路径中的class只对当前webapp可见;
commonloader、catalinaloader和sharedloader在tomcat容器初始化的一开始,即调用bootstrap的init方法时创建。catalinaloader会被设置为tomcat主线程的线程上下文类加载器,并且使用catalinaloader加载tomcat容器自身容器下的class。bootstrap的init方法的部分代码清单如下:
我们接着来看initclassloaders方法的实现:
创建类加载器的createclassloader方法的实现:
createclassloader最终使用classloaderfactory.createclassloader(locations, types, parent)方法创建classloader。我们回头看看securityclassload.securityclassload(catalinaloader)的实现:
securityclassload方法主要加载tomcat容器所需的class,包括:
tomcat核心class,即org.apache.catalina.core路径下的class;
org.apache.catalina.loader.webappclassloader$privilegedfindresourcebyname;
tomcat有关session的class,即org.apache.catalina.session路径下的class;
tomcat工具类的class,即org.apache.catalina.util路径下的class;
javax.servlet.http.cookie;
tomcat处理请求的class,即org.apache.catalina.connector路径下的class;
tomcat其它工具类的class,也是org.apache.catalina.util路径下的class;
我们以加载tomcat核心class的loadcorepackage方法为例,查看其实现:
至此,我们还没有看到webappclassloader。启动standardcontext的时候会创建webapploader,standardcontext的方法startinternal的部分代码如下:
从上面代码看到最后会调用webapploader的start方法,start又调用了startinternal方法,startinternal的实现如下:
最后我们看看createclassloader的实现:
至此,整个tomcat的类加载体系构建完毕。