Monday November 06, 2006
A Tangled Web
Class Loading in Open ESB
I've heard of some confusion about how class loading is addressed in Open ESB. Here's a high-level look at how the Open ESB class loading hierarchy is designed to work. This is a discussion at the functional level that does not delve too deeply into the implementation details.
Because Open ESB must be a JSR208-compliant implementation, the class loading approach must work within the rules defined in the JBI Specification. In section 7.3 of the specification, there is a detailed description of the class loading requirements for all JBI implementations.
In the Open ESB class loading implementation, an additonal design goal was to prevent installed JBI components (binding components and service engines) from directly accessing the JBI runtime implementation classes. All access to the JBI runtime implementation from within installed components must be through the public JBI interfaces defined by the JBI specification. In order to achieve this goal, the public JBI interfaces (javax.jbi.*) and the JBI implementation classes (com.sun.jbi.*) are packaged in separate jar files. During startup of Open ESB, separate class loaders are created for these jar files. One class loader, which I call the JBI shared class loader, has access only to the public JBI interfaces. Its parent class loader is the same class loader that is the parent for any other application running in the same environment, whether it be an application server or just a Java SE implementation. The second class loader, which I call the JBI runtime class loader has access to all of the JBI implementation classes. Its parent class loader is the JBI shared class loader.
Isolation of the JBI runtime implementation is achieved by not allowing the JBI runtime class loader to be the parent of any other class loader in the Open ESB system. Instead, all other class loaders created by the JBI runtime have the JBI shared class loader as their parents. This allows those class loaders to have access to the JBI runtime through the public JBI interfaces only.
Open ESB creates a separate class loader for each component and shared library, with the class path specified in the installation descriptor (jbi.xml) for the component or shared library. Each of these class loaders has the JBI shared class loader as its parent. Additionally, for each component which has dependencies upon installed shared libraries, there is a special delegating class loader that provides access to all shared libraries that are in the component's list of dependencies. This list is specified in the installation descriptor for the component.
In the normal Java class loading hierarchy, each class loader in a class loader chain delegates to its parent to see if the requested class is available from the parent. With this type of hierarchy, there is no way for a JBI component or shared library to provide its own version of a package if that package is also provided by the Java environment in which the JBI implementation is executing. A commonly-used example of this is an XML parser such as Xerces that may be supplied by the Java environment. A JBI component may require a specific version of an XML parser, so it must be able to protect itself from version changes that may be introduced by the Java environment in which JBI is executing.
To address the need for a JBI component or shared library to have its own version of a common package, JBI provides the ability to specify an inverted hierarchy for its class loaders. This is called self-first class loading. It can be specified for any JBI component or shared library in its installation descriptor. What this does is change the component's or shared library's class loader behavior to delegate to the parent class loader only if it doesn't find the requested class itself.
In order to prevent potential problems with allowing this inverted class loader hierarchy, the JBI runtime disallows self-first class loading for all classes in the java.* and javax.* packages.
Posted at 05:02PM Nov 06, 2006 by mwhite in Open ESB |