Building on the ideas introduced in the last article, a J2EE Application servers classloaders are explored in this installment. In particular, Websphere Application Server v.6.x Classloaders are introduced. The J2EE Spec provides some guidance regarding J2EE Application Servers, but as with so many aspects of J2EE, many details are left to the creativity of the implementer.
J2EE Containers generally add several additional classloaders to the base Classloader Hierarchy. In the strictest sense of the definition, these are all custom classloaders. But, from a J2EE Container standpoint, they are a required part of the system and should be viewed separately from custom classloaders that a J2EE Developer might create. It should be noted, that the J2EE-family of specifications does not give much in terms of Classloader architecture guidance. Once again, the leave-it-to-the-implementer’s-creativity manta shines through.
Note regarding Java & JVM Specification Versions
Websphere v6.1 is bulit on JSE 5 and JEE 1.4.
Websphere v6.0 is built on J2SE v1.4.2 and JEE 1.4. Specification versions for 1.4.2 are described here.
Specifications concerning J2EE Classloaders
The J2EE Specification does not say much about the classloaders used in a J2EE Container. Another example of the Java community leaving much detail to the creativity of the implementers. Section 18.104.22.168 discusses Context Classloaders and briefly describes possible classloader architectures. Section 8.2 briefly discusses classloader requirements in a J2EE container.
The Servlet v2.4 Specification is part of the J2EE v1.4 family of Specifications.
- This section also describes the concept of an application classloader (generally called a WAR or Application Classloader in our discussion).
- The web application classloader must load classes from WEB-INF/classes, first.
- Servlet classes must be loaded by the the web application classloader; otherwise, a 404 error must be returned.
The J2EE v1.4 family of specifications uses the EJB v2.1 Specification.
- Section 19.5.5 briefly mentions the use of classloaders with system value classes
- Section 21.6.9 discusses the use of classloaders with runtime security enforcement (as an example).
- Section 25.1.2 discusses runtime restrictions on Java code inside an EJB container; in particular, code must not attempt to create classloaders, obtain the current classloader, or set the context classloader.
Other specifications within the J2EE Specification family may define other classloader requirements. An exhaustive review of all relevant specifications is beyond the scope of this article. In general, careful review of your J2EE container’s documentation should cover the relevant details. Remember, every container has its own implementation.
Generally, most J2EE containers will implement an EJB/EAR Classloader and a WAR/Application Classloader. Typically, there is a one-to-one correspondence between EAR Classloaders and EAR files (Websphere offers the option to use this model or have a single classloader for N EAR files). Likewise, there is, typically, one WAR Classloader for each WAR file. Websphere can use a single classloader for all WARs in an EAR file or have all WAR & EAR classes loaded by a single EAR Classloader).
Three Classloaders Present in Every JVM
As outlined in the last article, there are three classloaders present in every Java Virtual Machine:
- Bootstrap Classloader
- Extensions Classloader
- Applicaton Classloader
We will not go into any further detail here.
Classloader hierarchy refers to the collection of classloaders used by a J2EE Container and the parent-child relationships. See the Delegation Model discussion defined by the Extensions Mechanism specification in the last article for more information.
Websphere v6.0 Classloader Hierarchy
Websphere v6.0 employed a legacy classloader hierarchy that was replaced in v6.1, but is important for historical considerations:
(Bootstrap, Extensions, Application)
The Runtime (or Websphere Extensions) Classloader handled loading all Websphere classes, JDBC Drivers, and third party drivers.
The Shared Library Classloader is only present if a shared Java library was defined. There could be more than one of these visible to different applications. Some documentation implies that the JAR file is added to the classpath of an existing classloader (EAR or WAR classloaders).
The Protection Classloader’s function is not well documented in the IBM documentation. It’s name implies that it serves a safety or security function beyond what Classloaders normally provide.
The documentation contradicts itself regarding the exact order of the Shared Library and Protection Classloaders in the Classloader Hierarchy.
The EAR/EJB Classloader loads classes from EJB jar files and other JAR files listed in the Class-Path entry of the META-INF/MANIFEST.MF file or located in the root directory of the EAR file. More information about MANIFEST.MF can be found here. See the EAR file packaging tutorial for more information.
The WAR or Application Classloader (not to be confused with the JVM Application/System Classloader) loads classes from the WEB-INF/classes and JAR files from WEB-INF/lib.
The rules of how WAR & EAR class loaders coexist are the same as described for the Websphere v6.1 classloaders.
<Websphere v6.1 Classloaders
Websphere v6.1 introduces a significant architectural change to the Classloader Hierarchy over v6.0.
(Bootstrap, Extensions, Application)
The three standard classloaders are ever present.
Next, the Websphere Extensions Classloader is responsible for loading the “guts” of Websphere. Every class of all Websphere subsystems is loaded by the Websphere Extensions Classloader–this was the same in v6.0. However, Websphere v6.1 uses the OSGI Component Architecture to package and load the pieces of Websphere. The OSGi classloaders are not part of the “classic” Classloader Hierarchy that has been described in the last article and here. For more information about OSGi see the next section.
The Shared Library Classloader is changed from Websphere v6.0. The Websphere v6.1 documentation tends to not explicitly list it. However, if you define a shared library, it can potentially be there. It also appears to be possible to attach Shared Libraries to specific classloaders, which would mean there isn’t an explicit classloader created. These Classloaders will be revisited at some point in the future.
The next two classloaders are unchanged from Websphere v6.0:
- Application/EJB/EAR Classloader
- WAR Classloader
OSGi is a set of specifications that “define a dynamic component system for Java.”. It’s goal is to lift developers out of JAR-hell (the Java equivalent of DLL hell. IBM chose the the OSGi framework as the new model for managing the many components and sub-systems of Websphere v6.1.
The Websphere Extensions Classloader is the Classloader Hierarchy’s entrance into an OSGi network of classloaders through an OSGi gateway classloader. Websphere is now packaged as a set of Websphere OSGi Bundles. Each Websphere OSGi Bundle has its own classloader.
The OSGi Specification can be found here.
The use of OSGi is completely transparent to the Websphere J2EE Developer.
In Websphere v6.x, each container has a Classloader Policy option that determines whether there is a single EAR/EJB Classloader for all EARs or one per EAR (the options are Single or Multiple).
Also, each WAR file has a Classloader Policy that determines the mapping of classloaders to WAR files. The options for this Classloader are “Class loader for each WAR file in applicaton” or “Single class loader for application”. For the first option, there would be a 1-1 mapping between classloaders and the WAR files in an EAR file that have this option specified. For the second, any WAR using this setting would have classes loaded by the EAR classloader.
If the container is configured to use a single EAR classloader and all WAR files are configured for “Single class loader for application”, there would be a single EJB/EAR classloader for all EAR files and WAR files in container.
The author has found using these options to build a sandbox effect where each EAR has its own classloader and ear WAR within an EAR has its own classloader has the fewest side effects and is the best from a security standpoint (in that there is little to no dependency on classes loaded from other WAR files).
Troubleshooting Classloader Problems
See the “Problem determination for classloader exceptions” section of the Redbook for a discussion of troubleshooting classloader problems in a Websphere container–the subject is done justice there.
Note, an environment where custom classloaders are used throws new pitfalls into this activity that are not covered by this document. The author has spent weeks debugging classloader issues related to a third-party application that used its own classloader to load dynamically generated and compiled Java code.