Class WeakHashtable
- java.lang.Object
-
- java.util.Dictionary<K,V>
-
- java.util.Hashtable
-
- org.apache.commons.logging.impl.WeakHashtable
-
- All Implemented Interfaces:
java.io.Serializable,java.lang.Cloneable,java.util.Map
public final class WeakHashtable extends java.util.HashtableImplementation ofHashtablethat usesWeakReference's 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 semantics of
Hashtableas closely as possible. It therefore does not accept null values or keys.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
HashtableinLogFactory. This application requires good liveliness forgetandput. Various tradeoffs have been made with this in mind.Usage: typical use case is as a drop-in replacement for the
Hashtableused inLogFactoryfor J2EE environments 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 callLogFactory.release(ClassLoader).org.apache.commons.logging.LogFactorychecks whether this class can be supported by the current JVM, and if so then uses it to store references to theLogFactoryimplementation it loads (rather than using a standard Hashtable instance). Having this class used instead ofHashtablesolves 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 ofjava.lang.ref.WeakReferenceand associates). And by the way, this extendsHashtablerather thanHashMapfor backwards compatibility reasons. See the documentation for methodLogFactory.createFactoryStorefor more details.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 a key in the "global"
LogFactory's factories member! IfLogFactory.release()is called whenever component is unloaded, the classloaders will be correctly garbage collected; this should be done by any container that bundles commons-logging by default. However, holding the classloader references weakly ensures that the classloader will be garbage collected without the container performing this step.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
LogFactoryis loaded by the container classloader but a subclass ofLogFactory[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 viagetClass().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
LogFactoryimplementation 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.- Since:
- 1.1
- Version:
- $Id: WeakHashtable.java 1435077 2013-01-18 10:51:35Z tn $
- See Also:
- Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static classWeakHashtable.EntryEntry implementationprivate static classWeakHashtable.ReferencedWrapper giving correct symantics for equals and hashcodeprivate static classWeakHashtable.WeakKeyWeakReference subclass that holds a hard reference to an associatedvalueand also makes accessible the Referenced object holding it.
-
Field Summary
Fields Modifier and Type Field Description private intchangeCountprivate static intMAX_CHANGES_BEFORE_PURGEThe maximum number of times put() or remove() can be called before the map will be purged of all cleared entries.private static intPARTIAL_PURGE_COUNTThe maximum number of times put() or remove() can be called before the map will be purged of one cleared entry.private java.lang.ref.ReferenceQueuequeueprivate static longserialVersionUIDSerializable version identifier.
-
Constructor Summary
Constructors Constructor Description WeakHashtable()Constructs a WeakHashtable with the Hashtable default capacity and load factor.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description booleancontainsKey(java.lang.Object key)java.util.Enumerationelements()java.util.SetentrySet()java.lang.Objectget(java.lang.Object key)booleanisEmpty()java.util.Enumerationkeys()java.util.SetkeySet()private voidpurge()Purges all entries whose wrapped keys have been garbage collected.private voidpurgeOne()Purges one entry whose wrapped key has been garbage collected.java.lang.Objectput(java.lang.Object key, java.lang.Object value)voidputAll(java.util.Map t)protected voidrehash()java.lang.Objectremove(java.lang.Object key)intsize()java.lang.StringtoString()java.util.Collectionvalues()
-
-
-
Field Detail
-
serialVersionUID
private static final long serialVersionUID
Serializable version identifier.- See Also:
- Constant Field Values
-
MAX_CHANGES_BEFORE_PURGE
private static final int MAX_CHANGES_BEFORE_PURGE
The maximum number of times put() or remove() can be called before the map will be purged of all cleared entries.- See Also:
- Constant Field Values
-
PARTIAL_PURGE_COUNT
private static final int PARTIAL_PURGE_COUNT
The maximum number of times put() or remove() can be called before the map will be purged of one cleared entry.- See Also:
- Constant Field Values
-
queue
private final java.lang.ref.ReferenceQueue queue
-
changeCount
private int changeCount
-
-
Method Detail
-
containsKey
public boolean containsKey(java.lang.Object key)
- Specified by:
containsKeyin interfacejava.util.Map- Overrides:
containsKeyin classjava.util.Hashtable- See Also:
Hashtable
-
elements
public java.util.Enumeration elements()
- Overrides:
elementsin classjava.util.Hashtable- See Also:
Hashtable
-
entrySet
public java.util.Set entrySet()
- Specified by:
entrySetin interfacejava.util.Map- Overrides:
entrySetin classjava.util.Hashtable- See Also:
Hashtable
-
get
public java.lang.Object get(java.lang.Object key)
- Specified by:
getin interfacejava.util.Map- Overrides:
getin classjava.util.Hashtable- See Also:
Hashtable
-
keys
public java.util.Enumeration keys()
- Overrides:
keysin classjava.util.Hashtable- See Also:
Hashtable
-
keySet
public java.util.Set keySet()
- Specified by:
keySetin interfacejava.util.Map- Overrides:
keySetin classjava.util.Hashtable- See Also:
Hashtable
-
put
public java.lang.Object put(java.lang.Object key, java.lang.Object value)- Specified by:
putin interfacejava.util.Map- Overrides:
putin classjava.util.Hashtable- See Also:
Hashtable
-
putAll
public void putAll(java.util.Map t)
- Specified by:
putAllin interfacejava.util.Map- Overrides:
putAllin classjava.util.Hashtable- See Also:
Hashtable
-
values
public java.util.Collection values()
- Specified by:
valuesin interfacejava.util.Map- Overrides:
valuesin classjava.util.Hashtable- See Also:
Hashtable
-
remove
public java.lang.Object remove(java.lang.Object key)
- Specified by:
removein interfacejava.util.Map- Overrides:
removein classjava.util.Hashtable- See Also:
Hashtable
-
isEmpty
public boolean isEmpty()
- Specified by:
isEmptyin interfacejava.util.Map- Overrides:
isEmptyin classjava.util.Hashtable- See Also:
Hashtable
-
size
public int size()
- Specified by:
sizein interfacejava.util.Map- Overrides:
sizein classjava.util.Hashtable- See Also:
Hashtable
-
toString
public java.lang.String toString()
- Overrides:
toStringin classjava.util.Hashtable- See Also:
Hashtable
-
rehash
protected void rehash()
- Overrides:
rehashin classjava.util.Hashtable- See Also:
Hashtable
-
purge
private void purge()
Purges all entries whose wrapped keys have been garbage collected.
-
purgeOne
private void purgeOne()
Purges one entry whose wrapped key has been garbage collected.
-
-