JBoss ClassLoader Overview and Goals
The following overview provides a fairly high level summary of the issues surrounding ClassLoading and some of the solutions that have been used to solve them.
It's main purpose is to provide a brief rational for the overall goals of the JBoss ClassLoader framework. It is not intended to be a detailed explanation which can be JBoss ClassLoader Introduction For those unfamiliar with certain terms aJBoss ClassLoader Glossary is provided.
ClassLoading is the JRE framework that allows user defined mechanisms to locate and load java classes. To take advantage of this feature a ClassLoader must be constructed by the user.
ClassLoading is one of those features within java where it is easy to do simple things and notoriously difficult to do and understand harder things. Part of the reason why ClassLoading is difficult to understand is that it is dealing with many different issues:
* Locating, defining and validating classes
* Assigning security permissions to the loaded classes
* Allowing multiple versions of a class to be loaded
* Controlling the visibility of one class (version) from another
* Serving as a contextual object on each thread (the "TCL")
The JBoss ClassLoader framework helps to make the use of ClassLoading simpler as well as providing additional features and abstractions to solve more complicated problems.
JRE Provided ClassLoaders
For simple use cases, the JRE provides a notion of "classpath". This is really just a ClassLoader that loads classes and resources from archives and directories defined on the command line.
The JRE also provides a URLClassLoader which effectively allows the user to create a "classpath" at runtime by providing a list of URLs.
The JRE ClassLoaders only provide a parent-child delegation model where the parent is asked first to load a class then the classloader the user has constructed. For example, the "classpath" will ask the "System ClassLoader" to load classes before looking at those classes defined by the user.
This works in simple cases but it makes it more difficult (if not impossible) to perform "hot deployment". Hot deployment is the mechanism where you can throw away a ClassLoader and then create a new one over some possibly changed classes. This allows classes to evolve without having to restart the runtime.
With peer delegation models such as the UnifiedClassLoader (UCL) of JBossAS 3 and 4, the swapping of ClassLoader can be much more fine grained.
One of the issues with "hot deployment" however is that other ClassLoaders can become tightly coupled if their classes are using "call-by-reference". i.e. Classes from one ClassLoader can reference classes from another ClassLoader that you want to "hot deploy".
The issue can be avoided by using "call-by-value" but it is less efficient.
A different solution is ClassLoader dependencies. That is for one ClassLoader to reference classes from another ClassLoader it must specify a dependency on the ClassLoader from which it wants to load classes. By making that information available to the ClassLoading framework, it can automatically redeploy dependent ClassLoaders when the ClassLoaders they depend upon change.
Often a class that is public is not really meant for public consumption. An example might be an internal class used by two different parts of the same framework.
Similarly, an application may use another framework but not want to expose that to users of the application. e.g. it could use a logging framework internally.
To support this idea, there should be a notion of "export" from a ClassLoader. That is only those packages that are stated as "exported" should be visible to classes from other ClassLoaders.
Class Annotation Scanning
Many of the JavaEE specs (and some other specs) are increasingly providing mechansims to define metadata using annotations on the classes rather than using xml files.
The issue this has for ClassLoading is how to locate all the classes that are part of a ClassLoader given their many different mechansims. e.g. there is no generic way to list the contents of a URL.
So as part of the pluggability mechanism for ClassLoader implementations, there should also be a way to plugin class discovery (assuming such a mechanism is possible for that implementation).
ClassLoader Isolation and Multiple Versions
People want to have their own versions of classes without interferance from other ClassLoaders running in the same JRE. The two main reasons for this are usually because of incompatiblity problems.
* A class doesn't understand contextual classloading or "leaks" information, usually through static variables
* A class has changed in an incompatible way between versions which would break some applications if they all tried to use the same version.
The typical solution is to use the "parent-child" delegation model, but in reverse. That is load to from the child first. This is called ClassLoader isolation or the "servlet spec model" since that spec recommends this type of ClassLoading.
This can be inefficient since you have multiple copies of the classes consuming memory. It also leads to many problems when classes in the isolated ClassLoader want to use classes in different ClassLoaders having different versions of the same classes.
An alternative solution is to assign a version to the ClassLoader and then use dependencies. i.e. there will be mutliple versions of the same classes in different ClassLoaders that can be chosen using the dependency mechanism. This allows ClassLoaders that want to use the same version to share the classes.
The consistency of the classes can also be checked at deployment time by the ClassLoading framework to ensure that applications that want to call each other by reference have the same class versions.
Goals of the JBoss ClassLoader Project
The goals for the JBoss ClassLoader project come directly from the issues raised above and some logical extensions of these requirements.
* Provide a simpler mechanism for plugging in ClassLoading rules without having to worry too much about the implementation or boiler plate details such as delegation models and export/import rules.
* Provide common features that a ClassLoader implementation can use
* Allow differently implementated ClassLoaders to work together
* Support peer delegation models including the JBoss UnifiedClassLoader and the OSGi models
* Provide a versioning mechanism for ClassLoaders
* Provide a pluggable dependency mechanism to resolve ClassLoading dependencies
* Allow ClassLoaders to take part in the full ClassLoading infrastructure regardless of how they are constructed, i.e. whether they are constructed explicitly in POJO configuration or implicitly from spec defined rules
* Allow the user to use only that part of the ClassLoading infrastructure as is required for their problem
* Define a common mechanism for Class Annotation Scanning across ClassLoader implementations