Improved javadocs for WeakHashTable. More readable explaination contributed by Simon Kitching.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@156689 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -23,10 +23,14 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>Implementation of <code>Hashtable</code> that uses <code>WeakReference</code>'s
|
||||
* to hold it's keys thus allowing them to be reclaimed by the garbage collector.
|
||||
* This class follows the symantics of <code>Hashtable</code> as closely as possible.
|
||||
* It therefore does not accept null values or keys.
|
||||
* <p>
|
||||
* to hold its keys thus allowing them to be reclaimed by the garbage collector.
|
||||
* The associated values are retained using strong references.</p>
|
||||
*
|
||||
* <p>This class follows the symantics of <code>Hashtable</code> as closely as
|
||||
* possible. It therefore does not accept null values or keys.</p>
|
||||
*
|
||||
* <p><strong>Note:</strong>
|
||||
* This is <em>not</em> intended to be a general purpose hash table replacement.
|
||||
* This implementation is also tuned towards a particular purpose: for use as a replacement
|
||||
* for <code>Hashtable</code> in <code>LogFactory</code>. This application requires
|
||||
* good liveliness for <code>get</code> and <code>put</code>. Various tradeoffs
|
||||
@@ -34,35 +38,82 @@ import java.util.*;
|
||||
* </p>
|
||||
* <p>
|
||||
* <strong>Usage:</strong> typical use case is as a drop-in replacement
|
||||
* for the <code>Hashtable</code> use in <code>LogFactory</code> for J2EE enviroments
|
||||
* for the <code>Hashtable</code> used in <code>LogFactory</code> for J2EE enviroments
|
||||
* running 1.3+ JVMs. Use of this class <i>in most cases</i> (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)}.
|
||||
* </p>
|
||||
*
|
||||
* <p><code>org.apache.commons.logging.LogFactory</code> looks to see whether this
|
||||
* class is present in the classpath, and if so then uses it to store
|
||||
* references to the <code>LogFactory</code> implementationd it loads
|
||||
* (rather than using a standard Hashtable instance).
|
||||
* Having this class used instead of <code>Hashtable</code> 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 <code>java.lang.ref.WeakReference</code> 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 <code>Hashtable</code> rather than <code>HashMap</code>
|
||||
* for backwards compatibility reasons. See the documentation
|
||||
* for method <code>LogFactory.createFactoryStore</code> for more details.</p>
|
||||
*
|
||||
* <p>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" <code>LogFactory</code>'s
|
||||
* factories member! If <code>LogFactory.release()</code> 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 <code>WeakHashtable</code> if the
|
||||
* class has explicitly been made available on the classpath.</p>
|
||||
*
|
||||
* <p>
|
||||
* In a particular usage scenario, use of <code>WeakHashtable</code> alone will
|
||||
* be insufficent to allow garbage collection of a classloader without a call to
|
||||
* <code>release</code>. If the abstract class <code>LogFactory</code> is
|
||||
* loaded by a parent classloader and a concrete subclass implementation of
|
||||
* <code>LogFactory</code> is loaded by a child classloader, the concrete
|
||||
* implementation will have a strong reference to the child classloader via the
|
||||
* chain <code>getClass().getClassLoader()</code>. The <code>WeakHashtable</code>
|
||||
* will have a strong reference to the <code>LogFactory</code> implementation as
|
||||
* one of the values in its map. This chain of references will prevent
|
||||
* collection of the child classloader.
|
||||
* </p>
|
||||
* Because the presence of this class in the classpath ensures proper
|
||||
* unload of components without the need to call method
|
||||
* {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release ClassLoader)},
|
||||
* it is recommended that this class be deployed along with the standard
|
||||
* commons-logging.jar file when using commons-logging in J2EE
|
||||
* environments (which will presumably be running on Java 1.3 or later).
|
||||
* There are no know ill effects from using this class.</p>
|
||||
*
|
||||
* <p>
|
||||
* Such a situation would typically only occur if commons-logging.jar were
|
||||
* <strong>Limitations:</strong>
|
||||
* 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.</p>
|
||||
*
|
||||
* <p> If the abstract class <code>LogFactory</code> is
|
||||
* loaded by the container classloader but a subclass of
|
||||
* <code>LogFactory</code> [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
|
||||
* <code>getClass().getClassLoader()</code>. This chain of references will prevent
|
||||
* collection of the child classloader.</p>
|
||||
*
|
||||
* <p>
|
||||
* 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 <code>LogFactory</code> implementation were
|
||||
* loaded by a child classloader (e.g. a web app classloader). If use of
|
||||
* a custom <code>LogFactory</code> subclass is desired, ensuring that the
|
||||
* custom subclass is loaded by the same classloader as <code>LogFactory</code>
|
||||
* will prevent problems. In normal deployments, the standard implementations
|
||||
* of <code>LogFactory</code> found in package <code>org.apache.commons.logging.impl</code>
|
||||
* will be loaded by the same classloader that loads <code>LogFactory</code>
|
||||
* itself, so use of the standard <code>LogFactory</code> implementations
|
||||
* should not pose problems.
|
||||
* servlet container) and a custom <code>LogFactory</code> implementation is
|
||||
* loaded by a child classloader (e.g. a web app classloader).</p>
|
||||
*
|
||||
* <p>To avoid this scenario, ensure
|
||||
* that any custom LogFactory subclass is loaded by the same classloader as
|
||||
* the base <code>LogFactory</code>. Creating custom LogFactory subclasses is,
|
||||
* however, rare. The standard LogFactoryImpl class should be sufficient
|
||||
* for most or all users.</p>
|
||||
*
|
||||
*
|
||||
* @author Brian Stansberry
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user