Class loading and Class Loaders
Introduction
Class loading, within the plethora of environments that Ehcache can be running, is a somewhat vexed issue.
Since ehcache-1.2, all classloading is done in a standard way in one utility class: ClassLoaderUtil
.
Plugin class loading
Ehcache allows plugins for events and distribution. These are loaded and created as follows:
/**
* Creates a new class instance. Logs errors along the way. Classes are loaded
* using the Ehcache standard classloader.
*
* @param className a fully qualified class name
* @return null if the instance cannot be loaded
*/
public static Object createNewInstance(String className) throws CacheException {
Class clazz;
Object newInstance;
try {
clazz = Class.forName(className, true, getStandardClassLoader());
} catch (ClassNotFoundException e) {
//try fallback
try {
clazz = Class.forName(className, true, getFallbackClassLoader());
} catch (ClassNotFoundException ex) {
throw new CacheException("Unable to load class " + className +
". Initial cause was " + e.getMessage(), e);
}
}
try {
newInstance = clazz.newInstance();
} catch (IllegalAccessException e) {
throw new CacheException("Unable to load class " + className +
". Initial cause was " + e.getMessage(), e);
} catch (InstantiationException e) {
throw new CacheException("Unable to load class " + className +
". Initial cause was " + e.getMessage(), e);
}
return newInstance;
}
/**
* Gets the <code>ClassLoader</code> that all classes in ehcache, and extensions,
* should use for classloading. All ClassLoading in Ehcache should use this one.
* This is the only thing that seems to work for all of the class loading
* situations found in the wild.
* @return the thread context class loader.
*/
public static ClassLoader getStandardClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
/**
* Gets a fallback <code>ClassLoader</code> that all classes in ehcache, and
* extensions, should use for classloading. This is used if the context class loader
* does not work.
* @return the <code>ClassLoaderUtil.class.getClassLoader();</code>
*/
public static ClassLoader getFallbackClassLoader() {
return ClassLoaderUtil.class.getClassLoader();
}
If this does not work for some reason a CacheException is thrown with a detailed error message.
Loading of ehcache.xml resources
If the configuration is otherwise unspecified, Ehcache looks for a configuration in the following order:
- Thread.currentThread().getContextClassLoader().getResource(“/ehcache.xml”)
- ConfigurationFactory.class.getResource(“/ehcache.xml”)
- ConfigurationFactory.class.getResource(“/ehcache-failsafe.xml”)
Ehcache uses the first configuration found. Note the use of “/ehcache.xml” which requires that ehcache.xml be placed at the root of the classpath, i.e. not in any package.
Classloading with Terracotta clustering
If Terracotta clustering is being used with valueMode=”serialization” then keys and values will be moved across the cluster in byte[] and deserialized on other nodes.
The classloaders used (in order) to instantiate those classes will be:
- Thread.currentThread().getContextClassLoader()
- The classloader that defined the CacheManager initially