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=13&rev2=14

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

  
  = Summary matrix =
  ||'''Leak cause'''||'''Detected by tomcat'''||'''Fixed by 
tomcat'''||'''Possible enhancements'''||
- ||[[#customThreadLocal|Custom ThreadLocal class]]||>=6.0.24||6.0.24-6.0.26 
but is unsafe. Made optional from 6.0.27|| [[#48837|Detect child 
classloaders]], [[#49159|BZ 49159]] ||
- ||[[#webappClassInstanceAsThreadLocalValue|Webapp class instance as 
ThreadLocal value]]||>=6.0.24||6.0.24-6.0.26 but is unsafe. Made optional from 
6.0.27|| [[#48837|Detect child classloaders]], [[#49159|BZ 49159]] ||
+ ||[[#customThreadLocal|Custom ThreadLocal class]]||>=6.0.24|| >= 7.0.6 ||  ||
+ ||[[#webappClassInstanceAsThreadLocalValue|Webapp class instance as 
ThreadLocal value]]||>=6.0.24|| >= 7.0.6 || ||
- ||[[#webappClassInstanceAsThreadLocalIndirectValue|Webapp class instance 
indirectly held through a ThreadLocal value]]||no||no||[[#49159|Renew threads 
in the worker pool]]||
+ ||[[#webappClassInstanceAsThreadLocalIndirectValue|Webapp class instance 
indirectly held through a ThreadLocal value]]||no|| >= 7.0.6 || ||
- ||[[#threadLocalPseudoLeak|ThreadLocal pseudo-leak]]||>=6.0.24||6.0.24-6.0.26 
but is unsafe. Made optional from 6.0.27||[[#49159|BZ 49159]]||
+ ||[[#threadLocalPseudoLeak|ThreadLocal pseudo-leak]]||>=6.0.24|| >= 7.0.6 || 
||
- ||[[#cclThreadSpawnedByWebApp|ContextClassLoader / Threads spawned by 
webapps]]||>=6.0.24||In 6.0.24-6.0.26 {{{TimerThread}}} are stopped but it may 
lead to problems. Optional from 6.0.27 with the 
{{{clearReferencesStopTimerThreads}}} flag. Other threads may be stopped with 
the {{{clearReferencesStopThreads}}} flag, but it's unsafe. ||[[#48837|Detect 
child classloaders]], Fix the application to stop the thread when the 
application is stopped||
+ ||[[#cclThreadSpawnedByWebApp|ContextClassLoader / Threads spawned by 
webapps]]||>=6.0.24||In 6.0.24-6.0.26 {{{TimerThread}}} are stopped but it may 
lead to problems. Optional from 6.0.27 with the 
{{{clearReferencesStopTimerThreads}}} flag. Other threads may be stopped with 
the {{{clearReferencesStopThreads}}} flag, but it's unsafe. || Fix the 
application to stop the thread when the application is stopped||
- ||[[#cclThreadSpawnedByCommonClassLoader|ContextClassLoader / Threads spawned 
by classes loaded by the common classloader]]||>=6.0.24||In 6.0.24-6.0.26 
{{{TimerThread}}} are stopped but it may lead to problems. Optional from 6.0.27 
with the {{{clearReferencesStopTimerThreads}}} flag. Other threads may be 
stopped with the {{{clearReferencesStopThreads}}} flag, but it's unsafe. 
||[[#48837|Detect child classloaders]], fix the offending code (set the correct 
CCL when spawning the thread)||
+ ||[[#cclThreadSpawnedByCommonClassLoader|ContextClassLoader / Threads spawned 
by classes loaded by the common classloader]]||>=6.0.24||In 6.0.24-6.0.26 
{{{TimerThread}}} are stopped but it may lead to problems. Optional from 6.0.27 
with the {{{clearReferencesStopTimerThreads}}} flag. Other threads may be 
stopped with the {{{clearReferencesStopThreads}}} flag, but it's unsafe. ||Fix 
the offending code (set the correct CCL when spawning the thread)||
  ||[[#cclThreadSpawnedByJRE|ContextClassLoader / Threads spawned by JRE 
classes]]|| no || >=6.0.24 pre-spawns some known offenders || ||
  ||[[#staticClassVariables|static class variables]]|| no ||> 6.0.? . Disabled 
by default with tomcat 7|| ||
  ||[[#LogFactory|LogFactory]]||  ||> 6.0.? || ||
@@ -82, +82 @@

  
  Hopefully tomcat 6.0.24 can detect the leak when the application is stopped: 
each Thread in the JVM is examined, and the internal structures of the Thread 
and {{{ThreadLocal}}} classes are introspected to see if either the 
{{{ThreadLocal}}} instance or the value bound to it were loaded by the 
{{{WebAppClassLoader}}} of the application being stopped.
  
+ In this particular case, the leak is detected and a message is logged. 
- In this particular case, the leak is detected and a message is logged. Tomcat 
6.0.24 to 6.0.26 modify internal structures of the JDK ({{{ThreadLocalMap}}}) 
to remove the reference to the {{{ThreadLocal}}} instance, but this is unsafe 
(see [[#48895]]) so that it became optional and disabled by default from 6.0.27.
+ Tomcat 6.0.24 to 6.0.26 modify internal structures of the JDK 
({{{ThreadLocalMap}}}) to remove the reference to the {{{ThreadLocal}}} 
instance, but this is unsafe (see [[#48895]]) so that it became optional and 
disabled by default from 6.0.27.
+ Starting with Tomcat 7.0.6, the threads of the pool are renewed so that the 
leak is safely fixed. 
  
  {{{
  Mar 16, 2010 11:47:24 PM org.apache.catalina.loader.WebappClassLoader 
clearThreadLocalMap
  SEVERE: A web application created a ThreadLocal with key of type 
[test.MyThreadLocal] (value [test.MyThreadLocal@4dbb9a58]) and a value of type 
[test.MyCounter] (value [test.MyCounter@57922f46]) but failed to remove it when 
the web application was stopped. To prevent a memory leak, the ThreadLocal has 
been forcibly removed.
  }}}
  
- '''Note''': this particular leak was actually already cured by previous 
versions of tomcat, because static references of classes loaded by the 
webappclassloader are nullified ([[#clearReferencesStopThreads|see later]]).
+ '''Note''': this particular leak was actually already cured by previous 
versions of tomcat 6, because static references of classes loaded by the 
webappclassloader are nullified ([[#clearReferencesStopThreads|see later]]).
  
  <<Anchor(webappClassInstanceAsThreadLocalValue)>>
  === Webapp class instance as ThreadLocal value ===
@@ -176, +178 @@

  }
  }}}
  
- We have more or less the same kind of leak as the previous one, but this time 
tomcat 6.0.24 does not detect the leak when stopping the application (and does 
not fix it). The problem is that when it inspects the entries of 
{{{ThreadLocalMap}}}, it checks whether either the key or the value is an 
instance of a class loaded by the webapp classloader. Here the key is an 
instance of {{{ThreadLocal}}}, and the value is an instance of 
java.util.{{{ArrayList}}}.
+ We have more or less the same kind of leak as the previous one, but this time 
tomcat does not detect the leak when stopping the application.
+ The problem is that when it inspects the entries of {{{ThreadLocalMap}}}, it 
checks whether either the key or the value is an instance of a class loaded by 
the webapp classloader. Here the key is an instance of {{{ThreadLocal}}}, and 
the value is an instance of java.util.{{{ArrayList}}}.
  
  The "Find leaks" button in tomcat manager will report the leak when asked :
  {{{
@@ -187, +190 @@

  }}}
  
  But it does not give any clue about what caused the leak, we would need to 
make a heapdump and analyse it with some tool like 
[[http://www.eclipse.org/mat|Eclipse MAT]].
+ 
+ Tomcat 7.0.6 and later fix this leak by renewing threads in the pool.
  
  <<Anchor(threadLocalPseudoLeak)>>
  == ThreadLocal pseudo-leak ==
@@ -228, +233 @@

  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-6.0.26 "speeds up" the removal of stale entries (and thus fixes 
the pseudo-leak), by calling {{{expungeStaleEntries()}}} for each thread that 
has some stale entries. Since it's not thread-safe, it has been made optional 
and disabled by default from 6.0.27.
+ 
+ Tomcat 7.0.6 and later fix the problem by renewing threads in the pool.
  
  == Threads ContextClassLoader ==
  <<Anchor(cclThreadSpawnedByWebApp)>>
@@ -359, +366 @@

  
  Instead of trying to stop such threads, tomcat prefers to force the creation 
of such threads when the container is started, before webapps are started. The 
{{{JreMemoryLeakPreventionListener}}} does it for a few known offenders in the 
JRE.
  
- == Child classloaders ==
- 
- When an app is stopped, Tomcat 6.0.24 and later detect leaks caused by 
{{{ThreadLocal}}}s and Threads context classloader only by checking for the 
current {{{WebAppClassLoader}}}. If a child classloader is involved, the leak 
is not detected. That should be [[#48837|improved in a future release]].
- 
  <<Anchor(staticClassVariables)>>
  == static class variables ==
  
@@ -402, +405 @@

   * 
<<Anchor(48837)>>[[https://issues.apache.org/bugzilla/show_bug.cgi?id=48837|48837]]
 - Memory leaks protection does not cure leaks triggered by JSP pages code
   * <<Anchor(49159)>>[[https://issues.apache.org/bugzilla/show_bug.cgi?id= 
49159|49159]] - Improve ThreadLocal memory leak clean-up
   * [[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4957990|Sun bug 
4957990]] - In some cases the Server JVM fails to collect classloaders. 
According to [[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4957990|this 
page]] it should have been fixed with java 6u16 but actually it was not. It 
seems to be fixed with 6u21 (documented 
[[http://download.java.net/jdk6/6u21/promoted/b03/changes/JDK6u21.list.html|here]]
 and verified by the author of this wiki page).
+  * [[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498|Sun bug 
6916498]] - An exception can keep a classloader in memory if the stack trace 
that was recorded when it was created contains a reference to one of its 
classes. Some fixes have been made in tomcat (see 
[[https://issues.apache.org/bugzilla/show_bug.cgi?id=50460|BZ 50460]]), but 
some library or JRE code may still create a leak that is undetected by tools 
because of this JVM bug.
  
  ----
  [[CategoryFAQ]]

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

Reply via email to