当Tomcat5启动以后,它创建一系列类加载器。这些类加载器以父子关系组织在一起,父类加载器在子类加载器的上面:
|
System
|
Common
/ \
Catalina Shared
/ \
Webapp1 Webapp2 ...
这些类加载器所扮演的角色,以及它们可以见到的类和资源的规则如下:
如上图所示,Tomcat5 在初始化的时候创建如下类加载器:
Bootstrap - 这个类加载器可以加载Java虚拟机的运行时基础类,以及在系统扩展目录($JAVA_HOME/jre/lib/ext
)中的所有Jar包中的类。注意-一些JVM可能用多个类加载器来实现它,或者它是根本不能被看见的。
System - 这个类加载器一般可以加载CLASSPATH环境变量的内容。所有这个类对于Tomcat内部的类和web应用程序的都是可见的。尽管如此,标准的Tomcat5启动脚本($CATALINA_HOME/bin/catalina.sh
或 %CATALINA_HOME%\bin\catalina.bat
)都会忽略CLASSPATH环境变量,取而代之的是从如下仓库加载:
- $CATALINA_HOME/bin/bootstrap.jar - 包含Tomcat5 服务器初始化的main()方法,以及所需的类加载器的实现类。
- $JAVA_HOME/lib/tools.jar - 包括把JSP页面编译成Serlet类所需的"javac"编译器.
- $CATALINA_HOME/bin/commons-logging-api.jar - Jakarta commons logging API.
- $CATALINA_HOME/bin/commons-daemon.jar - Jakarta commons daemon API.
- jmx.jar - The JMX 1.2 实现.
Common - 这个类加载器可以使一些附加的类对于Tomcat内部的类和web应用程序可见。正常情况下,应用程序不应该替换它。所有$CATALINA_HOME/common/classes目录下的未打包类和资源,以及$CATALINA_HOME/commons/endorsed、$CATALINA_HOME/commons/i18n、$CATALINA_HOME/common/lib目录下的Jar包中的类和资源都是这个类加载器的加载对象。默认情况,包括如下内容:
- commons-el.jar - Jakarta commons el, Jasper用的EL表达式实现
- jasper-compiler.jar - The JSP 2.0 编译器.
- jasper-compiler-jdt.jar - The Eclipse JDT Java 编译器.
- jasper-runtime.jar - The JSP 2.0 运行库.
- jsp-api.jar - The JSP 2.0 API.
- naming-common.jar - Tomcat5的JNDI 实现,用于内存命名环境
- naming-factory.jar - Tomcat5的JNDI 实现,用于企业级资源引用(EJB, connection pools).
- naming-factory-dbcp.jar - Jakarta commons DBCP, 为Web应用程序提供JDBC连接池。这个类已经从默认的org.apache.commons包中移出。
- naming-java.jar - java命名空间处理器.
- naming-resources.jar - The specialized JNDI naming context implementation used to represent the static resources of a web application. This is not related to the support of the J2EE ENC, and cannot be removed.
- servlet-api.jar - The Servlet 2.4 API.
- tomcat-i18n-**.jar - Optional JARs containing resource bundles for other languages. As default bundles are also included in each individual JAR, they can be safely removed if no internationalization of messages is needed.
Catalina - 这个类加载器主要加载Tomcat5自己所需要的类和资源。这些类和资源对于Web应用程序是完全不可见的。在$CATALINA_HOME/server/classes目录下的所有类和资源,$CATALINA_HOME/server/lib下的所有Jar包中类和资源是这个类加载器的加载对象。默认情况,包括个如下内容:
- catalina.jar - Tomcat5中Catalina Servlet容器的实现部分。
- catalina-ant.jar - 在管理web应用程序时要用倒的一些Ant任务。
- catalina-optional.jar - 一些Catalina可选组件。
- commons-modeler.jar - Tomcat通过JMX暴露其内部对象是用的一些MBean实现。
- servlets-xxxxx.jar - 这些类同内部的Servlet一起提供Tomcat的部分功能,它们都是独立的,所以如果不需要相应的服务可以将其删除。或者它们可以从属于特定的安全管理器。
- tomcat-coyote.jar - Coyote API.。
- tomcat-http.jar - 标准的Java HTTP/1.1 连接器.。
- tomcat-ajp.jar -
AJP
web 服务器的连接器,一般用于Apache,iPlanet iAS和 iWS.。 - tomcat-util.jar - Tomcat连接器需要的工具类。
Shared - 这个类加载器用于把一些类和资源共享给所有的web应用程序。(除非Tomcat内部的类也需要访问这些类,在这种情况下你应该把它们放在Common类加载能加载的地方). 在$CATALINA_BASE/shared/classes目录下的所有未打包类和资源,以及$CATALINA_BASE/shared/lib目录下的所有Jar包中的类和资源可以被其加载。如果通过$CATALINA_BASE环境变量来从同一个tomcat程序运行了多个在实例,那么这个类加载器的仓库是相对于$CATALINA_BASE而不是$CATALINA_HOME。
WebappX - 系统会为部署在一个Tomcat实例中的每个应用程序创建一个这样的类加载器,它们为所属的应用程序加载类。所有你的web应用程序包的/WEB-INF/classes目录下的类和资源,以及
/WEB-INF/lib 目录下的所有Jar包中的类和资源是这个类的加载对象。这些类和资源仅对这个应用程序可见,并且这个应用程序也看不见其他应用程序的类和资源。
就像上面所描述的,web应用程序的类加载的加载流程与默认的Java 2的类记载托管模型是不一样的。当有一个请求需要应用程序的WebappX 类加载器加载一个类的时候,这个类加载器是首先到自己的仓库中查找,而不是先交给上面的类加载器查找。这里有一些例外。JRE的基础类是不能被覆盖的。对于其他一些类(如J2SE 1.4+中的XML解析器组件),可以使用J2SE1.4的签名特性。最后任何包括servlet API类的Jar包会被忽略。Tomcat5中的其他的类加载器使用正常托管模式。
这样在一个web应用程序中,类和资源的加载顺序是这样:
- Bootstrap classes of your JVM
- System class loader classses (described above)
- /WEB-INF/classes of your web application
- /WEB-INF/lib/*.jar of your web application
- $CATALINA_HOME/common/classes
- $CATALINA_HOME/common/endorsed/*.jar
- $CATALINA_HOME/common/i18n/*.jar
- $CATALINA_HOME/common/lib/*.jar
- $CATALINA_BASE/shared/classes
- $CATALINA_BASE/shared/lib/*.jar