edu.rice.cs.util.classloader
Class StickyClassLoader

java.lang.Object
  |
  +--java.lang.ClassLoader
        |
        +--edu.rice.cs.util.classloader.StickyClassLoader

public class StickyClassLoader
extends ClassLoader

A ClassLoader that works as the union of two classloaders, but always tries to delegate to the first of these. The purpose for this class is to ensure that classes loaded transitively due to some class's loading are also loaded with the right classloader. Here's the problem: Say that class A contains a reference to class B, but the specific B is unknown to clients of class A. Class A is loadable by the standard classloader, but class B needs to be loaded with a (known) custom classloader.

If A were loaded using the standard classloader, it would fail because this would cause the transitive loading of B to be done by the system loader as well. If A were loaded with the custom loader, the same thing would happen -- the custom loader would delegate to the system loader to load A (since it doesn't load non-custom-loader-requiring classes), but this would associate class A with the system classloader. (Every class is associated with the loader that called ClassLoader.defineClass(byte[], int, int) to define it in the JVM.) This association would make B be loaded by the standard loader!

To get around this problem, we use this class, which acts mostly as a union of two classloaders. The trick, however, is that the StickyClassLoader has itself associated with all classes it loads, even though the actual work is done by the two loaders it delegate to. (It does this by calling ClassLoader.findResource(java.lang.String) on the subordinate loaders to get the class data, but then by calling ClassLoader.defineClass(byte[], int, int) itself to preserve the association.

Version:
$Id: StickyClassLoader.java,v 1.7 2002/02/21 04:56:25 brianstoler Exp $

Inner classes inherited from class java.lang.ClassLoader
ClassLoader.NativeLibrary
 
Field Summary
private  String[] _classesToLoadWithOld
           
private  ClassLoader _newLoader
           
 
Fields inherited from class java.lang.ClassLoader
bootstrapClassPath, classes, defaultDomain, defaultPermissions, getClassLoaderPerm, initialized, loadedLibraryNames, nativeLibraries, nativeLibraryContext, nocerts, package2certs, packages, parent, scl, sclSet, sys_paths, systemNativeLibraries, usr_paths
 
Constructor Summary
StickyClassLoader(ClassLoader newLoader, ClassLoader oldLoader)
          Creates a sticky class loader with the given primary and secondary loaders to join together.
StickyClassLoader(ClassLoader newLoader, ClassLoader oldLoader, String[] classesToLoadWithOld)
          Creates a sticky class loader with the given primary and secondary loaders to join together.
 
Method Summary
 URL getResource(String name)
          Gets the requested resource, looking first in the new loader and then in the old loader.
protected  Class loadClass(String name, boolean resolve)
          Loads the given class, delegating first to the new class loader and then second to the old class loader.
 
Methods inherited from class java.lang.ClassLoader
, addClass, check, checkCerts, checkPackageAccess, compareCerts, copyFrom, defineClass, defineClass, defineClass, defineClass0, definePackage, findBootstrapClass, findBootstrapClass0, findClass, findLibrary, findLoadedClass, findNative, findResource, findResources, findSystemClass, getBootstrapClassPath, getBootstrapResource, getBootstrapResources, getCallerClassLoader, getDefaultDomain, getGetClassLoaderPerm, getPackage, getPackages, getParent, getResourceAsStream, getResources, getSystemClassLoader, getSystemResource, getSystemResourceAsStream, getSystemResources, initializePath, isAncestor, loadClass, loadClassInternal, loadLibrary, loadLibrary0, removeSystemClassLoader, resolveClass, resolveClass0, setSigners
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, registerNatives, toString, wait, wait, wait
 

Field Detail

_newLoader

private final ClassLoader _newLoader

_classesToLoadWithOld

private final String[] _classesToLoadWithOld
Constructor Detail

StickyClassLoader

public StickyClassLoader(ClassLoader newLoader,
                         ClassLoader oldLoader)
Creates a sticky class loader with the given primary and secondary loaders to join together. All classes will be attempted to be loaded with the primary loader, and the secondary will be used as a fallback.
Parameters:
newLoader - Primary loader
oldLoader - Secondary loader

StickyClassLoader

public StickyClassLoader(ClassLoader newLoader,
                         ClassLoader oldLoader,
                         String[] classesToLoadWithOld)
Creates a sticky class loader with the given primary and secondary loaders to join together. All classes will be attempted to be loaded with the primary loader (except for classes in classesToLoadWithOld), and the secondary will be used as a fallback.
Parameters:
newLoader - Primary loader
oldLoader - Secondary loader
classesToLoadWithOld - All class names in this array will be loaded only with the secondary classloader. This is vital to ensure that only one copy of some classes are loaded, since two differently loaded versions of a class act totally independantly! (That is, they have different, incompatible types.) Often it'll be necessary to make key interfaces that are used between components get loaded via one standard classloader, to ensure that things can be cast to that interface.
Method Detail

getResource

public URL getResource(String name)
Gets the requested resource, looking first in the new loader and then in the old loader.
Overrides:
getResource in class ClassLoader
Parameters:
name - Name of resource to find
Returns:
URL of the resource if found/accessible, or null if not.

loadClass

protected Class loadClass(String name,
                          boolean resolve)
                   throws ClassNotFoundException
Loads the given class, delegating first to the new class loader and then second to the old class loader. The returned Class object will have its ClassLoader (Class.getClassLoader()) set to be this. This is very important because it causes classes that are loaded due to this class being loaded (ancestor classes/interfaces, referenced classes, etc) to use the same loader. There are a few exceptions to this explanation:
  1. If the class is in java.* or javax.*, it will be loaded using ClassLoader.getSystemClassLoader(). This is because only the system loader is allowed to load system classes! Also: sun.*.
  2. If the class name is in the list of classes to load with the old class loader (passed to constructor), the new loader is not considered when trying to load the class. This is useful to make sure that certain classes (or interfaces) only have one copy in the system, to ensure that you can cast to that class/interface regardless of which loader loaded the other class.
Overrides:
loadClass in class ClassLoader