Author: skitching
Date: Sat Mar 12 20:20:38 2005
New Revision: 157309
URL: http://svn.apache.org/viewcvs?view=rev&rev=157309
Log:
Updated javadoc only.
Modified:
jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java
Modified:
jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java
URL:
http://svn.apache.org/viewcvs/jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java?view=diff&r1=157308&r2=157309
==============================================================================
---
jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java
(original)
+++
jakarta/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ContextClassLoaderLocal.java
Sat Mar 12 20:20:38 2005
@@ -20,12 +20,81 @@
import java.util.WeakHashMap;
/**
- * A value that is provided per (thread) context classloader.
- * Patterned after ThreadLocal.
- * There is a separate value used when Thread.getContextClassLoader() is null.
- * This mechanism provides isolation for web apps deployed in the same
container.
- * <strong>Note:</strong> A WeakHashMap bug in several 1.3 JVMs results in a
memory leak
- * for those JVMs.
+ * An instance of this class represents a value that is provided per (thread)
+ * context classloader.
+ *
+ * <p>Occasionally it is necessary to store data in "global" variables
+ * (including uses of the Singleton pattern). In applications which have only
+ * a single classloader such data can simply be stored as "static" members on
+ * some class. When multiple classloaders are involved, however, this approach
+ * can fail; in particular, this doesn't work when the code may be run within a
+ * servlet container or a j2ee container, and the class on which the static
+ * member is defined is loaded via a "shared" classloader that is visible to
all
+ * components running within the container. This class provides a mechanism for
+ * associating data with a ClassLoader instance, which ensures that when the
+ * code runs in such a container each component gets its own copy of the
+ * "global" variable rather than unexpectedly sharing a single copy of the
+ * variable with other components that happen to be running in the same
+ * container at the same time (eg servlets or EJBs.)</p>
+ *
+ * <p>This class is strongly patterned after the java.lang.ThreadLocal
+ * class, which performs a similar task in allowing data to be associated
+ * with a particular thread.</p>
+ *
+ * <p>When code that uses this class is run as a "normal" application, ie
+ * not within a container, the effect is identical to just using a static
+ * member variable to store the data, because Thread.getContextClassLoader
+ * always returns the same classloader (the system classloader).</p>
+ *
+ * <p>Expected usage is as follows:<br>
+ * <pre>
+ * public class SomeClass {
+ * private static final ContextClassLoaderLocal global
+ * = new ContextClassLoaderLocal() {
+ * protected Object initialValue() {
+ * return new String("Initial value");
+ * };
+ *
+ * public void testGlobal() {
+ * String s = (String) global.get();
+ * System.out.println("global value:" + s);
+ * buf.set("New Value");
+ * }
+ * </pre>
+ * </p>
+ *
+ * <p><strong>Note:</strong> This class takes some care to ensure that when
+ * a component which uses this class is "undeployed" by a container the
+ * component-specific classloader and all its associated classes (and their
+ * static variables) are garbage-collected. Unfortunately there is one
+ * scenario in which this does <i>not</i> work correctly and there
+ * is unfortunately no known workaround other than ensuring that the
+ * component (or its container) calls the "unset" method on this class for
+ * each instance of this class when the component is undeployed. The problem
+ * occurs if:
+ * <ul>
+ * <li>the class containing a static instance of this class was loaded via
+ * a shared classloader, and</li>
+ * <li>the value stored in the instance is an object whose class was loaded
+ * via the component-specific classloader (or any of the objects it refers
+ * to were loaded via that classloader).</li>
+ * </ul>
+ * The result is that the map managed by this object still contains a strong
+ * reference to the stored object, which contains a strong reference to the
+ * classloader that loaded it, meaning that although the container has
+ * "undeployed" the component the component-specific classloader and all the
+ * related classes and static variables cannot be garbage-collected. This is
+ * not expected to be an issue with the commons-beanutils library as the only
+ * classes which use this class are BeanUtilsBean and ConvertUtilsBean and
+ * there is no obvious reason for a user of the beanutils library to subclass
+ * either of those classes.</p>
+ *
+ * <p><strong>Note:</strong> A WeakHashMap bug in several 1.3 JVMs results in
+ * a memory leak for those JVMs.</p>
+ *
+ * <p><strong>Note:</strong> Of course all of this would be unnecessary if
+ * containers required each component to load the full set of classes it
+ * needs, ie avoided providing classes loaded via a "shared" classloader.</p>
*
* @see java.lang.Thread#getContextClassLoader
* @author Eric Pabst
@@ -60,11 +129,11 @@
* Gets the instance which provides the functionality for [EMAIL
PROTECTED] BeanUtils}.
* This is a pseudo-singleton - an single instance is provided per
(thread) context classloader.
* This mechanism provides isolation for web apps deployed in the same
container.
- * @return the object currently associated with the
+ * @return the object currently associated with the context-classloader of
the current thread.
*/
public synchronized Object get() {
// synchronizing the whole method is a bit slower
- // but guarentees no subtle threading problems, and there's no
+ // but guarantees no subtle threading problems, and there's no
// need to synchronize valueByClassLoader
// make sure that the map is given a change to purge itself
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]