ClassLoaders and Web Applications
This post has changed to correct some errors
In the previous posting I described the class loader heirarchy, and mentioned that you can use standard Java API classes and methods to create a branching tree structure of loaders. I also touched on the fact that Java EE application servers use this to ensure that each web application gets its own private load path for classes.
However, the loading rules as I described them don't quite apply to web applications, so this article is intended to cover the differences.
I'm describing the way things work in Tomcat; other servers should be doing something similar.
Tomcat Loader Heirarchy
As I mentioned in the previous post, ordinary Java applications have three loaders at run time: the Boot loader, which is usually native, platform-specific code built into the JVM and searches the standard class libraries; the Extension class loader, which searches JARs in the
Tomcat adds two more levels to this heirarchy for web applications: at the bottom, a
Tomcat's system class loader is the parent of this
The
The
Servlet API loader rules
The Servlet API specification is the root of things here; it says that the loader search algorithm for web applications should ensure that classes and JARs packaged in the WAR should be searched before any of the servlet container's library JAR files, but should not allow the application to override any of the standard Java classes.
Tomcat'sthen searches its own repositories, then finally delegates to its parent. This ensures that JRE classes can't be overridden (they get searched first) and that repositories are searched before Tomcat's
That covers the important differences that apply to web applications. There is one other small aspect that I'd like to mention.
Getting Resources
The Servlet API specification also mandates that web applications must be able to locate their own resources using
In the previous posting I described the class loader heirarchy, and mentioned that you can use standard Java API classes and methods to create a branching tree structure of loaders. I also touched on the fact that Java EE application servers use this to ensure that each web application gets its own private load path for classes.
However, the loading rules as I described them don't quite apply to web applications, so this article is intended to cover the differences.
I'm describing the way things work in Tomcat; other servers should be doing something similar.
Tomcat Loader Heirarchy
As I mentioned in the previous post, ordinary Java applications have three loaders at run time: the Boot loader, which is usually native, platform-specific code built into the JVM and searches the standard class libraries; the Extension class loader, which searches JARs in the
$JAVA_HOME/jre/lib/ext
directory; and the System class loader, which searches directories and JARs specified in the CLASSPATH
. The Extension loader is the parent of the System loader, and the Boot loader is (in practice) the parent of the Extension loader. Slight correction: some JVMs combine the Boot and Extension loaders into one.Tomcat adds two more levels to this heirarchy for web applications: at the bottom, a
WebappClassLoader
(one for each deployed web application) with the application's WEB-INF/classes
and all the archive files in the WEB-INF/lib
directory set as the search path; and above that a StandardClassLoader
(one only for the whole server), with its search path set as Tomcat's lib
directory and all the archive files in it. Tomcat's system class loader is the parent of this
StandardClassLoader
and has its search path set to include Tomcat's bootstrap.jar
file and little else.The
StandardClassLoader
class is a subclass of URLClassLoader
but doesn't add or override anything from that class - it's functionally identical.The
WebappClassLoader
class, on the other hand, subclasses URLClassLoader
but reimplements most if not all of the methods. Here's why...Servlet API loader rules
The Servlet API specification is the root of things here; it says that the loader search algorithm for web applications should ensure that classes and JARs packaged in the WAR should be searched before any of the servlet container's library JAR files, but should not allow the application to override any of the standard Java classes.
Tomcat's
WebappClassLoader
achieves the first part of this (searching the WAR contents first) by not delegating searches to its parent until after it has already searched its own repositories - the opposite of the usual procedure. (I'm not clear on how it ensures that standard classes don't get overridden - the code in that area is tricky to follow.) Major correction required here: In fact the WebAppClassLoader
delegates directly to the System class loader first, lib
contents.That covers the important differences that apply to web applications. There is one other small aspect that I'd like to mention.
Getting Resources
The Servlet API specification also mandates that web applications must be able to locate their own resources using
ClassLoader.getResource()
. The heirarchy as described achieves this. However the specification says nothing about the static ClassLoader.getSystemResource()
method and in fact this method is of little use in web applications because the System class loader doesn't know anything about the web application's resources (as you can see from where it is in the heirarchy as described).Labels: Pure Java, Web Development