@@ -0,0 +1,3223 @@
+/*%0A * Copyright (C) 2011-2014 Chris Vest (mr.chrisvest@gmail.com)%0A *%0A * Licensed under the Apache License, Version 2.0 (the %22License%22);%0A * you may not use this file except in compliance with the License.%0A * You may obtain a copy of the License at%0A *%0A *         http://www.apache.org/licenses/LICENSE-2.0%0A *%0A * Unless required by applicable law or agreed to in writing, software%0A * distributed under the License is distributed on an %22AS IS%22 BASIS,%0A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.%0A * See the License for the specific language governing permissions and%0A * limitations under the License.%0A */%0Apackage stormpot;%0A%0Aimport org.junit.Test;%0Aimport org.junit.Ignore;%0A%0Aimport java.lang.ref.WeakReference;%0A%0Aimport static org.junit.Assert.assertNull;%0A%0Apublic class ThreadLocalWeakRefTest %7B%0A  /**%0A   * Many Java web servers and containers go out of their way to find and null%0A   * out ThreadLocals that an application might have created. Question is, is%0A   * that really necessary?%0A   */%0A  @Ignore%0A  @Test public void%0A  threadsWeaklyReferenceThreadLocalValues() %7B%0A    // Hypothesis: When we loose the reference to a ThreadLocal (e.g. by a%0A    // web app being redeployed and getting a soft restart), and no other%0A    // references to that object exists, then it should eventually be garbage%0A    // collected.%0A%0A    Object obj = new Object();%0A    ThreadLocal%3CObject%3E threadLocal = new ThreadLocal%3CObject%3E();%0A    WeakReference%3CObject%3E weakReference = new WeakReference%3CObject%3E(obj);%0A    threadLocal.set(obj);%0A%0A    // The stack of every thread is a GC-root. We have a strong reference to%0A    // obj through the variable on our stack. When we clear it out, the only%0A    // strong reference that will be left, will be through the threadLocal.%0A    obj = null;%0A%0A    // When we loose the reference to the threadLocal, then the values it%0A    // referred to will no longer be strongly referenced by our thread.%0A    threadLocal = null;%0A%0A    // Our obj is now in principle garbage, though we still have a%0A    // weakReference to it. The GC does not yet know this, because only the%0A    // threadLocal object itself is now weakly referenced. We clear out that%0A    // weak reference with a run of the GC.%0A    System.gc();%0A%0A    // The entry in our ThreadLocalMap is now stale. It still exists, and%0A    // strongly references our obj, but it will be cleared next time our%0A    // ThreadLocalMap does its clean-up procedure. We cannot invoke the%0A    // clean-up procedure directly, but sufficient perturbation of the%0A    // ThreadLocalMap will bring it about.%0A    ThreadLocal%3CObject%3E a = new ThreadLocal%3CObject%3E();%0A    a.set(new Object());%0A    ThreadLocal%3CObject%3E b = new ThreadLocal%3CObject%3E();%0A    b.set(new Object());%0A%0A    // The entry has now been removed, and our obj is now weakly referenced%0A    // by our weakReference above. Invoking another round of GC will clear it.%0A    System.gc();%0A%0A    // The obj has now been collected because all references are gone.%0A    // We observe this by the weakReference being null.%0A    assertNull(weakReference.get());%0A%0A    // This test passes on Java 6, 7 and 8, with default GC settings.%0A    // I haven't tried alternative GC settings, but you are welcome to do that.%0A  %7D%0A%7D%0A

Add an example of how ThreadLocal values are cleared by the GC