|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectjava.util.Dictionary<K,V>
java.util.Hashtable
org.apache.commons.logging.impl.WeakHashtable
public final class WeakHashtable
Implementation of Hashtable
that uses WeakReference
'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 symantics of Hashtable
as 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 Hashtable
in LogFactory
. This application requires
good liveliness for get
and put
. Various tradeoffs
have been made with this in mind.
Usage: typical use case is as a drop-in replacement
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 LogFactory.release(ClassLoader)
.
org.apache.commons.logging.LogFactory
checks whether this class
can be supported by the current JVM, 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 by the way, this extends Hashtable
rather than HashMap
for backwards compatibility reasons. See the documentation
for method LogFactory.createFactoryStore
for 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! If LogFactory.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 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.
Nested Class Summary | |
---|---|
private static class |
WeakHashtable.Entry
Entry implementation |
private static class |
WeakHashtable.Referenced
Wrapper giving correct symantics for equals and hashcode |
private static class |
WeakHashtable.WeakKey
WeakReference subclass that holds a hard reference to an associated value and also makes accessible
the Referenced object holding it. |
Field Summary | |
---|---|
private int |
changeCount
|
private static 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. |
private static 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. |
private java.lang.ref.ReferenceQueue |
queue
|
Constructor Summary | |
---|---|
WeakHashtable()
Constructs a WeakHashtable with the Hashtable default capacity and load factor. |
Method Summary | |
---|---|
boolean |
containsKey(java.lang.Object key)
|
java.util.Enumeration |
elements()
|
java.util.Set |
entrySet()
|
java.lang.Object |
get(java.lang.Object key)
|
boolean |
isEmpty()
|
java.util.Enumeration |
keys()
|
java.util.Set |
keySet()
|
private void |
purge()
Purges all entries whose wrapped keys have been garbage collected. |
private void |
purgeOne()
Purges one entry whose wrapped key has been garbage collected. |
java.lang.Object |
put(java.lang.Object key,
java.lang.Object value)
|
void |
putAll(java.util.Map t)
|
protected void |
rehash()
|
java.lang.Object |
remove(java.lang.Object key)
|
int |
size()
|
java.lang.String |
toString()
|
java.util.Collection |
values()
|
Methods inherited from class java.util.Hashtable |
---|
clear, clone, contains, containsValue, equals, hashCode |
Methods inherited from class java.lang.Object |
---|
finalize, getClass, notify, notifyAll, wait, wait, wait |
Field Detail |
---|
private static final int MAX_CHANGES_BEFORE_PURGE
private static final int PARTIAL_PURGE_COUNT
private java.lang.ref.ReferenceQueue queue
private int changeCount
Constructor Detail |
---|
public WeakHashtable()
Method Detail |
---|
public boolean containsKey(java.lang.Object key)
containsKey
in interface java.util.Map
containsKey
in class java.util.Hashtable
Hashtable
public java.util.Enumeration elements()
elements
in class java.util.Hashtable
Hashtable
public java.util.Set entrySet()
entrySet
in interface java.util.Map
entrySet
in class java.util.Hashtable
Hashtable
public java.lang.Object get(java.lang.Object key)
get
in interface java.util.Map
get
in class java.util.Hashtable
Hashtable
public java.util.Enumeration keys()
keys
in class java.util.Hashtable
Hashtable
public java.util.Set keySet()
keySet
in interface java.util.Map
keySet
in class java.util.Hashtable
Hashtable
public java.lang.Object put(java.lang.Object key, java.lang.Object value)
put
in interface java.util.Map
put
in class java.util.Hashtable
Hashtable
public void putAll(java.util.Map t)
putAll
in interface java.util.Map
putAll
in class java.util.Hashtable
Hashtable
public java.util.Collection values()
values
in interface java.util.Map
values
in class java.util.Hashtable
Hashtable
public java.lang.Object remove(java.lang.Object key)
remove
in interface java.util.Map
remove
in class java.util.Hashtable
Hashtable
public boolean isEmpty()
isEmpty
in interface java.util.Map
isEmpty
in class java.util.Hashtable
Hashtable
public int size()
size
in interface java.util.Map
size
in class java.util.Hashtable
Hashtable
public java.lang.String toString()
toString
in class java.util.Hashtable
Hashtable
protected void rehash()
rehash
in class java.util.Hashtable
Hashtable
private void purge()
private void purgeOne()
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |