Index: src/java/org/apache/lucene/util/CloseableThreadLocal.java =================================================================== --- src/java/org/apache/lucene/util/CloseableThreadLocal.java (revision 830934) +++ src/java/org/apache/lucene/util/CloseableThreadLocal.java (working copy) @@ -17,11 +17,11 @@ * limitations under the License. */ -import java.util.Map; +import java.io.Closeable; +import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Iterator; -import java.lang.ref.WeakReference; -import java.io.Closeable; +import java.util.Map; /** Java's builtin ThreadLocal has a serious flaw: * it can take an arbitrarily long amount of time to @@ -41,7 +41,15 @@ * separately holding a hard reference to each stored * value. When you call {@link #close}, these hard * references are cleared and then GC is freely able to - * reclaim space by objects stored in it. */ + * reclaim space by objects stored in it. + * + * We can not rely on Java 5's {@link ThreadLocal#remove()} as + * it only removes the value for the caller thread, whereas + * CloseableThreadLocal takes care of all threads values in one call. + * Note that this class should not be used outside Lucene; + * for more more details, see + * {@link "https://issues.apache.org/jira/browse/LUCENE-2017"} + */ public class CloseableThreadLocal implements Closeable { @@ -88,6 +96,11 @@ // all values we were storing are weak (unless somewhere // else is still using them) and so GC may reclaim them: hardRefs = null; + // Take care of the current thread right now; others will be + // taken care of via the WeakReference's. + if (t != null) { + t.remove(); + } t = null; } }