Catalina Class Loader Hierarchy

[Introduction] [Overview] [Process] [Notes]


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.

Overview Diagram

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:

                      /      \
                 Catalina   Shared
                           /     \
                       Webapp1  Webapp2 ...
                         /          /
                      Jasper1   Jasper2

The usage of and repositories contained in each class loader are described further below:

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.

Web Application Class Loading Process

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 calling the Class.forName() method), the following processing occurs to locate and load the requested class:

  1. The loadClass() method of the WebappX class loader is called to load the specified class.
  2. If this class has been previously loaded by this class loader, the cached copy is returned again. This avoids having to do potentially expensive I/O every time a class is requested.
  3. If the class to be loaded is a Java core class (java.*), it is loaded directly by the System class loader.
  4. If Catalina is running under a security manager (which is normally the case), the class loading permissions in the policy file are checked. If the specified policies prohibit loading the named class, the class loader will log the violation attempt and return a ClassNotFoundException.
  5. If this class loader's delegate property 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/classes or a JAR file in WEB-INF/lib.
  6. The local repositories are searched next, starting with the WEB-INF/classes directory (if it exists), and then the JAR files in WEB-INF/lib.
  7. If we still have not found the class, and did not delegate earlier, we delegate to our parent class loader (i.e. the Shared class loader, which will attempt to load the class itself or delegate upwards. This process continues until the class is found, or we have reached the top of the class loader hierarchy.
  8. If the class has still not been found, ClassNotFoundException is thrown, as required by the Javadocs for a class loader.

A similar pattern is followed when you call Class.getResource() or Class.getResourceAsStream() to access resources that are co-resident with your classes.

Miscellaneous Notes

Class Loader Information Exposed For Web Applications

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:

A Note On XML Parsers

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 thrown.

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:

Additional Information

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:

$Id: classloaders.html,v 2003/04/09 15:16:07 ytp Exp $