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=10&rev2=11 -------------------------------------------------- = Summary matrix = ||'''Leak cause'''||'''Detected by tomcat'''||'''Fixed by tomcat'''||'''Possible enhancements'''|| - ||[[#customThreadLocal|Custom ThreadLocal class]]||>=6.0.24||>=6.0.24|| [[#48837|Detect child classloaders]], [[#48895|improve thread safety]] || - ||[[#webappClassInstanceAsThreadLocalValue|Webapp class instance as ThreadLocal value]]||>=6.0.24||>=6.0.24|| [[#48837|Detect child classloaders]], [[#48895|improve thread safety]] || + ||[[#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]] || - ||[[#webappClassInstanceAsThreadLocalIndirectValue|Webapp class instance indirectly held through a ThreadLocal value]]||no||no||Renew threads in the worker pool|| + ||[[#webappClassInstanceAsThreadLocalIndirectValue|Webapp class instance indirectly held through a ThreadLocal value]]||no||no||[[#49159|Renew threads in the worker pool]]|| - ||[[#threadLocalPseudoLeak|ThreadLocal pseudo-leak]]||>=6.0.24||>=6.0.24||[[#48895|improve thread safety]]|| - ||[[#cclThreadSpawnedByWebApp|ContextClassLoader / Threads spawned by webapps]]||>=6.0.24||{{{TimerThread}}} are stopped. Other threads may be stopped if {{{clearReferencesStopThreads}}} is set to true on the Context ||[[#48837|Detect child classloaders]], [[#48971|don't stop TimerThread by default]]|| - ||[[#cclThreadSpawnedByCommonClassLoader|ContextClassLoader / Threads spawned by classes loaded by the common classloader]]||>=6.0.24||{{{TimerThread}}} are stopped. Other threads may be stopped if {{{clearReferencesStopThreads}}} is set to true on the Context ||[[#48837|Detect child classloaders]], [[#48971|don't stop TimerThread by default]]|| + ||[[#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]]|| + ||[[#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|| + ||[[#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)|| ||[[#cclThreadSpawnedByJRE|ContextClassLoader / Threads spawned by JRE classes]]|| no || >=6.0.24 pre-spawns some known offenders || || ||[[#staticClassVariables|static class variables]]|| no ||> 6.0.? || || ||[[#LogFactory|LogFactory]]|| ||> 6.0.? || || @@ -84, +84 @@ 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, a message is logged and internal structures of the JDK ({{{ThreadLocalMap}}}) are modified to remove the reference to the {{{ThreadLocal}}} instance. + 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. {{{ Mar 16, 2010 11:47:24 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap @@ -145, +145 @@ If the servlet is invoked at least once, the webapp classloader would not be GCed when the app is stopped: since the classloader of {{{ThreadScopedHolder}}} is the common classloader, it remains forever which is as expected. But its {{{ThreadLocal}}} instance has a value bound to it (for the non-terminated thread(s) that served the sevlet), which is an instance of a class loaded by the webapp classloader... - Here again, tomcat 6.0.24 will detect and fix the leak by removing this {{{ThreadLocal}}} reference from each Thread. + Here again, tomcat >=6.0.24 will detect the leak : {{{ Mar 17, 2010 10:23:13 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap SEVERE: A web application created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.threadlo...@44676e3f]) and a value of type [test.leak.threadlocal.value.MyCounter] (value [test.leak.threadlocal.value.mycoun...@62770d2e]) but failed to remove it when the web application was stopped. To prevent a memory leak, the ThreadLocal has been forcibly removed. @@ -229, +229 @@ 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. + 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. == Threads ContextClassLoader == <<Anchor(cclThreadSpawnedByWebApp)>> @@ -352, +352 @@ SEVERE: A web application appears to have started a TimerThread named [Timer-0] via the java.util.Timer API but has failed to stop it. To prevent a memory leak, the timer (and hence the associated thread) has been forcibly cancelled. }}} + So the leak is fixed, but unfortunately there's a side effect : [[#48971|it broke webapp B eviction timer]]. That's why stopping {{{TimerThread}}} has been made optional from 6.0.27. - So the leak is fixed, but unfortunately there's a side effect : [[#48971|it broke webapp B eviction timer]]. - - Note: as of 6.0.24, by default tomcat stops threads of class {{{java.util.TimerThread}}} whose context classloader is the {{{WebAppClassLoader}}} of the app being stopped. It does not stop other threads, it only warns about them. It can try to stop them if the {{{clearReferencesStopThreads}}} option of the standard context is set to true. <<Anchor(cclThreadSpawnedByJRE)>> === Threads spawned by JRE classes === @@ -365, +363 @@ == Child classloaders == - When an app is stopped, Tomcat 6.0.24 detects 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]]. + 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 == @@ -406, +404 @@ * <<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(48895)>>[[https://issues.apache.org/bugzilla/show_bug.cgi?id=48895|48895]] - !WebAppClassLoader.clearThreadLocalMap() concurrency issues * <<Anchor(48971)>>[[https://issues.apache.org/bugzilla/show_bug.cgi?id=48971|48971]] - memory leak protection : stopping !TimerThreads should be optional and disabled by default + * <<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). --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org