Like many server applications, Catalina installs a variety of class loaders
(that is, classes that extend
java.lang.ClassLoader) to allow
different portions of the container, and the web applications running on the
container, to have access to different repositories of available classes and
resources. This mechanism is used to provide the functionality defined in
the Servlet API Specification, version 2.3 (public draft 1) -- in particular
sections 9.4 and 9.6.
The remainder of this document provides an overview diagram of the parent - child relationships between each class loader that is created, more detailed information about the content and use of each class loader, and some additional relevant notes.
In a Java2 environment, class loaders are arranged in a parentage tree. Normally, when a class loader is asked to load a class (or get a resource), it delegates the request upwards first, and only searches its local repositories if the parent class loader(s) cannot find the requested class or resource. The model for web applications differs slightly from this, as discussed further below.
The class loaders that Catalina uses are organized as follows, where the parent class loader is above the child class loaders:
Bootstrap | System | Common / \ Catalina Shared / \ Webapp1 Webapp2 ... / / Jasper1 Jasper2
The usage of and repositories contained in each class loader are described further below:
java.*classes. Depending on how your particular JVM is organized, this may actually be more than one class loader, or may not exist at all. It is generally not referenced directly.
CLASSPATHenvironment variable, and contains classes that must be visible to both the Catalina internal classes and to web applications. The standard Catalina startup scripts assemble the following repositories for the system class path:
$CATALINA_HOME/bin/bootstrap.jar- The Bootstrap class that is used to initialize the Catalina server, and the class loader implementation classes it depends on.
$JAVA_HOME/lib/tools.jar- The Javac compiler used to compile the servlets generated from JSP pages (if present on your system).
$CATALINA_HOME/common/classesdirectory (if it exists), and all JAR files in the
$CATALINA_HOME/common/libdirectory (if it exists). The latter group normally includes the following:
jndi.jar- The Java Naming and Directory Service API classes (loaded only if not already included in the JDK, as they are with JDK 1.3).
naming.jar- The JNDI implementation used by Tomcat 4 itself.
servlet.jar- The servlet and JSP API classes.
$CATALINA_HOME/server/classesdirectory (if it exists), and all JAR files in the
$CATALINA_HOME/server/libdirectory (if it exists). Because these classes are loaded from a separate class loader, which is not visible to the Webapp class loader, they are not visible to web applications.
$CATALINA_HOME/classesdirectory (if it exists), and all JAR files in the
$CATALINA_HOME/libdirectory (if it exists). All of the classes in these repositories will be visible to all web applications, so they may be used to share information between web apps. (NOTE - this behavior is specific to Tomcat 4.0, and will not necessarily be portable to other containers.)
WEB-INF/classesdirectory (if it exists), plus all JAR files in the
WEB-INF/libdirectory, for this web app. Because of the parentage hierarchy, web applications can indirectly see (and therefore load classes from) the Shared, Common, System, and Bootstrap class loaders, but not from the Catalina or JasperX class loaders.
$CATALINA_HOME/jasperdirectory, which normally includes the Jasper compiler classes and the XML parser that they require. Because the parent of this class loader is the WebappX class loader for this application, the JSP compiler can see all of the JavaBean and other classes that are part of this application, but the application classes cannot see anything loaded from here (and, in particular, will not have access to the XML parser loaded by this class loader.
As you can see from the above descriptions, the contents of any
CLASSPATH environment variable already existing in your server
is totally ignored. If you want to make a JAR file available to all web
applications, you must place a copy of this file in the
$CATALINA_HOME/lib directory so that it becomes part of the
Shared class loader's repositories.
When a servlet (or JSP page) within a web application references a class
for the first time (either by using the
new operator or by
Class.forName() method), the following processing
occurs to locate and load the requested class:
loadClass()method of the WebappX class loader is called to load the specified class.
java.*), it is loaded directly by the System class loader.
delegateproperty is set to
true(which is not the default), we will ask our parent class loader to load this class before looking locally. This is the standard Java2 delegation model, but prevents a web application from overriding a class from the Shared class loader with its own copy from
WEB-INF/classesor a JAR file in
WEB-INF/classesdirectory (if it exists), and then the JAR files in
ClassNotFoundExceptionis thrown, as required by the Javadocs for a class loader.
A similar pattern is followed when you call
Class.getResourceAsStream() to access resources that are
co-resident with your classes.
Certain web application components (such as the Jasper JSP page compiler servlet, require additional information related to class loading to operate successfully. To avoid creating dependencies between the Jasper and Catalina code bases, this information is exposed as a set of servlet context attributes that are initialized when the web application is started. The following context attributes are created:
Previously, the Jasper page compiler was loaded in the
Shared class loader, along with the XML parser that it
requires. This had the side effect of causing this XML parser to be visible
to all web applications, through the inheritance hierarchy. However, this
causes problems if the JAR files of the selected XML parser are sealed (as are
the JAR files in the JAXP 1.1 reference implementation, for example) -- any
attempt to load your own XML parser (such as Xerces) from
WEB-INF/lib would cause "package sealing violation" errors to be
Now that the XML parser required by Jasper is loaded from the JasperX class loader, rather than the Shared class loader, this problem no longer occurs. However, any web application that relied on an XML parser being made available by Catalina will fail, because this is no longer true by default. If your web application requires an XML parser, you have three choices:
WEB-INF/libdirectory of your web application.
$CATALINA_HOME/libdirectory so that they are available to all web applications. Note that this is likely to introduce "package sealing violation" problems again, so this option is only practical if your applications do not require JSP pages.
For more information about class loaders in general, see the Java Language Specification, and the Javadocs for the following classes:
The implementation class for all Catalina internal class loaders is
StandardClassLoader. Required and available optional packages
are described using the
Extension class. For more information,
see the source code and/or Javadocs for the following classes: