From 23df003ef1f01cfb8ba4295c04c5dba9073c7f20 Mon Sep 17 00:00:00 2001
From: Robert Burrell Donkin Implementation of
+ * to hold its keys thus allowing them to be reclaimed by the garbage collector.
+ * The associated values are retained using strong references. This class follows the symantics of Note:
+ * This is not intended to be a general purpose hash table replacement.
* This implementation is also tuned towards a particular purpose: for use as a replacement
* for
* Usage: typical use case is as a drop-in replacement
- * for the The reason all this is necessary is due to a issue which
+ * arises during hot deploy in a J2EE-like containers.
+ * Each component running in the container owns one or more classloaders; when
+ * the component loads a LogFactory instance via the component classloader
+ * a reference to it gets stored in the static LogFactory.factories member,
+ * keyed by the component's classloader so different components don't
+ * stomp on each other. When the component is later unloaded, the container
+ * sets the component's classloader to null with the intent that all the
+ * component's classes get garbage-collected. However there's still a
+ * reference to the component's classloader from the "global"
- * In a particular usage scenario, use of Hashtable that uses WeakReference's
- * to hold it's keys thus allowing them to be reclaimed by the garbage collector.
- * This class follows the symantics of Hashtable as closely as possible.
- * It therefore does not accept null values or keys.
- * Hashtable as closely as
+ * possible. It therefore does not accept null values or keys.Hashtable in LogFactory. This application requires
* good liveliness for get and put. Various tradeoffs
@@ -34,36 +38,83 @@ import java.util.*;
* Hashtable use in LogFactory for J2EE enviroments
+ * for the Hashtable used in LogFactory for J2EE enviroments
* running 1.3+ JVMs. Use of this class in most cases (see below) will
* allow classloaders to be collected by the garbage collector without the need
* to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}.
* org.apache.commons.logging.LogFactory looks to see whether this
+ * class is present in the classpath, and if so then uses it to store
+ * references to the LogFactory implementationd it loads
+ * (rather than using a standard Hashtable instance).
+ * Having this class used instead of Hashtable solves
+ * certain issues related to dynamic reloading of applications in J2EE-style
+ * environments. However this class requires java 1.3 or later (due to its use
+ * of java.lang.ref.WeakReference and associates) and therefore cannot be
+ * included in the main logging distribution which supports JVMs prior to 1.3.
+ * And by the way, this extends Hashtable rather than HashMap
+ * for backwards compatibility reasons. See the documentation
+ * for method LogFactory.createFactoryStore for more details.LogFactory's
+ * factories member! If LogFactory.release() is called whenever component
+ * is unloaded (as happens in some famous containers), the classloaders will be correctly
+ * garbage collected.
+ * However, holding the classloader references weakly ensures that the classloader
+ * will be garbage collected without programmatic intervention.
+ * Unfortunately, weak references are
+ * only available in java 1.3+, so this code only uses WeakHashtable if the
+ * class has explicitly been made available on the classpath.WeakHashtable alone will
- * be insufficent to allow garbage collection of a classloader without a call to
- * release. If the abstract class LogFactory is
- * loaded by a parent classloader and a concrete subclass implementation of
- * LogFactory is loaded by a child classloader, the concrete
- * implementation will have a strong reference to the child classloader via the
- * chain getClass().getClassLoader(). The WeakHashtable
- * will have a strong reference to the LogFactory implementation as
- * one of the values in its map. This chain of references will prevent
- * collection of the child classloader.
- *
- * Such a situation would typically only occur if commons-logging.jar were
- * loaded by a parent classloader (e.g. a server level classloader in a
- * servlet container) and a custom LogFactory implementation were
- * loaded by a child classloader (e.g. a web app classloader). If use of
- * a custom LogFactory subclass is desired, ensuring that the
- * custom subclass is loaded by the same classloader as LogFactory
- * will prevent problems. In normal deployments, the standard implementations
- * of LogFactory found in package org.apache.commons.logging.impl
- * will be loaded by the same classloader that loads LogFactory
- * itself, so use of the standard LogFactory implementations
- * should not pose problems.
+ * Limitations:
+ * There is still one (unusual) scenario in which a component will not
+ * be correctly unloaded without an explicit release. Though weak references
+ * are used for its keys, it is necessary to use
+ * strong references for its values.
If the abstract class LogFactory is
+ * loaded by the container classloader but a subclass of
+ * LogFactory [LogFactory1] is loaded by the component's
+ * classloader and an instance stored in the static map associated with the
+ * base LogFactory class, then there is a strong reference from the LogFactory
+ * class to the LogFactory1 instance (as normal) and a strong reference from
+ * the LogFactory1 instance to the component classloader via
+ * getClass().getClassLoader(). This chain of references will prevent
+ * collection of the child classloader.
+ * Such a situation occurs when the commons-logging.jar is
+ * loaded by a parent classloader (e.g. a server level classloader in a
+ * servlet container) and a custom LogFactory implementation is
+ * loaded by a child classloader (e.g. a web app classloader).
To avoid this scenario, ensure
+ * that any custom LogFactory subclass is loaded by the same classloader as
+ * the base LogFactory. Creating custom LogFactory subclasses is,
+ * however, rare. The standard LogFactoryImpl class should be sufficient
+ * for most or all users.