Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tomcat Wiki" for change 
notification.

The "MemoryLeakProtection" page has been changed by SylvainLaurent.
http://wiki.apache.org/tomcat/MemoryLeakProtection?action=diff&rev1=4&rev2=5

--------------------------------------------------

  
  == ThreadLocal pseudo-leak ==
  
+ Suppose we have the same {{{MyCounter}}} class as above (in the webapp) and 
the following servlet :
+ {{{
+ public class LeakingServlet extends HttpServlet {
+       private ThreadLocal<MyCounter> myThreadLocal = new 
ThreadLocal<MyCounter>();
+ 
+       protected void doGet(HttpServletRequest request,
+                       HttpServletResponse response) throws ServletException, 
IOException {
+ 
+               MyCounter counter = myThreadLocal.get();
+               if (counter == null) {
+                       counter = new MyCounter();
+                       myThreadLocal.set(counter);
+               }
+ 
+               response.getWriter().println(
+                               "The current thread served this servlet " + 
counter.getCount()
+                                               + " times");
+               counter.increment();
+       }
+ 
+       @Override
+       public void destroy() {
+               super.destroy();
+               // normally not needed, just to make my point
+               myThreadLocal = null;
+       }
+ }
+ }}}
+ 
+ Notice that the {{{ThreadLocal}}} instance is referenced through an instance 
variable, not a static one.
+ 
+ Sun's implementation of {{{ThreadLocal}}} (and {{{WeakHashMap}}}) too is such 
that {{{ThreadLocalMap}}} entries whose key is GCed are not immediately removed.
+ (The key is a weak reference to the {{{ThreadLocal}}} instance, see 
{{{java.lang.ThreadLocal.ThreadLocalMap.Entry<T> in JDK 5/6}}}. And there's no 
daemon thread waiting on a {{{ReferenceQueue}}}). Instead, it's only during 
subsequent uses of {{{ThreadLocal}}} features that each Thread removes the 
abandoned {{{ThreadLocalMap.Entry}}} entries (see 
{{{ThreadLocalMap.expungeStaleEntries()}}}.
+ 
+ If many threads were used to serve our leaking webapp, but after we stop it 
only a couple of threads are enough to serve other webapps, one could have some 
threads that are no longer used, waiting for some work. Since those threads are 
blocked, they have no interaction with their {{{ThreadLocalMap}}} (i.e. there's 
no {{{ThreadLocal}}} value bound to them or removed), so that there's no 
opportunity to {{{expungeStaleEntries()}}}.
+ 
+ Tomcat 6.0.24 "speeds up" the removal of stale entries (and thus fixes the 
pseudo-leak), by calling {{{expungeStaleEntries()}}} for each thread that has 
some stale entries.
+ 
  == Threads ContextClassLoader ==
  === Threads spawned by JRE classes ===
  === Threads spawned by classes loaded by the common classloader ===

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to