1
0

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:
Robert Burrell Donkin
2005-03-09 21:13:21 +00:00
parent 01f84f3a7c
commit 23df003ef1

View File

@@ -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,36 +38,83 @@ 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
* 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.
* <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 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
*/
public final class WeakHashtable extends Hashtable {
@@ -434,4 +485,4 @@ public final class WeakHashtable extends Hashtable {
return referenced;
}
}
}
}