> -----Ursprüngliche Nachricht----- > Von: Christopher Schultz <ch...@christopherschultz.net> > Gesendet: Freitag, 25. März 2022 14:05 > An: users@tomcat.apache.org > Betreff: Re: AW: Question to possible memory leak by Threadlocal variable > > Thomas, > > On 3/24/22 05:49, Thomas Hoffmann (Speed4Trade GmbH) wrote: > > > > > >> -----Ursprüngliche Nachricht----- > >> Von: Mark Thomas <ma...@apache.org> > >> Gesendet: Donnerstag, 24. März 2022 09:32 > >> An: users@tomcat.apache.org > >> Betreff: Re: Question to possible memory leak by Threadlocal variable > >> > >> On 24/03/2022 07:57, Thomas Hoffmann (Speed4Trade GmbH) wrote: > >> > >> <snip/> > >> > >>> Is it correct, that every spawned thread must call tl.remove() to > >>> cleanup all > >> the references to prevent the logged warning (and not only the main > >> thread)? > >> > >> Yes. Or the threads need to exit. > >> > >>> Second question is: How might it cause a memory leak? > >>> The threads are terminated and hold a reference to this static > >>> variable. But > >> on the other side, that class A is also eligible for garbage > >> collection after undeployment. > >>> So both, the thread class and the class A are ready to get garbage > >>> collected. Maybe I missed something (?) > >> > >> It sounds as if the clean-up is happening too late. Tomcat expects > >> clean-up to be completed once contextDestroyed() has returned for all > >> ServLetContextListeners. If the clean-up is happening asynchronously > (e.g. > >> the call is made to stop the threads but doesn't wait until the > >> threads have > >> stopped) you could see this message. > >> > >> In this case it sounds as if you aren't going to get a memory leak > >> but Tomcat can't tell that at the point it checks. > >> > >> Mark > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > >> For additional commands, e-mail: users-h...@tomcat.apache.org > > > > Hello Mark, > > thanks for the information. > > The shutdown of the framework is currently placed within the destroy() > method of a servlet (with load on startup). > > At least the debugger shows that servlet-->destroy() is executed before > the method checkThreadLocalMapForLeaks() runs. > > I will take a look, whether the threads already exited. > > Tomcat only checks its own request-processing threads for ThreadLocals, so > any threads created by the application or that library are unrelated to the > warning you are seeing. > > Any library which saves ThreadLocals from request-processing threads is > going to have this problem if the objects are of types loaded by the webapp > ClassLoader. > > There are a few ways to mitigate this, but they are ugly and it would be > better if the library didn't use ThreadLocal storage, or if it would use > vanilla > classes from java.* and not its own types. > > You say that those objects are eligible for GC after the library shuts down, > but that's not true: anything you stick in ThreadLocal storage is being held > ... > by the ThreadLocal storage and won't be GC'd. If an object can't be collected, > the java.lang.Class defining it can't be collected, and therefore the > ClassLoader which loaded it (the webapp > ClassLoader) can't be free'd. We call this a "pinned ClassLoader" and it still > contains all of the java.lang.Class instances that the ClassLoader ever loaded > during its lifetime. If you reload repeatedly, you'll see un-collectable > ClassLoader instances piling up in memory which is > *definitely* a leak. > > The good news for you is that Tomcat has noticed the problem and will, over > time, retire and replace each of the affected Threads in its request- > processing thread pool. As those Thread objects are garbage-collected, the > TheradLocal storage for each is also collected, etc. and *eventually* your > leak > will be resolved. But it would be better not to have one in the first place. > > Why not name the library? Why anonymize the object type if it's > org.apache.something? > > -chris
Hello Chris, I didn't want to blame any library 😉 But as you ask for it, I send more details. Regarding the ThreadLocal thing: I thought that the threadlocal variables are stored within the Thread-class in the member variable "ThreadLocal.ThreadLocalMap threadLocals": https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/share/classes/java/lang/Thread.java So I thought, when the thread dies, these variables will also be released and automatically removed from the ThreadLocal variable / instance (?) I considered the ThreadLocal class as just the manager of the thread's member variable "threadLocals". Regarding the library: The full log-message is: 12-Mar-2022 15:01:16.302 SCHWERWIEGEND [Thread-15] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [java.lang.ThreadLocal.SuppliedThreadLocal] (value [java.lang.ThreadLocal$SuppliedThreadLocal@2121cbad]) and a value of type [org.apache.camel.impl.DefaultCamelContext.OptionHolder] (value [org.apache.camel.impl.DefaultCamelContext$OptionHolder@338d0413]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. The blamed class is this version: https://github.com/apache/camel/blob/camel-3.14.x/core/camel-core-engine/src/main/java/org/apache/camel/impl/DefaultCamelContext.java Within our app we have a startup servlet with: Servlet-> init: context = new DefaultCamelContext(); Servlet -> destroy: context.stop(); The stop-method will call the doStop() method of this class (via the class hierarchy DefaultCamelContext --> SimpleCamelContext --> AbstractCamelContext). After the destroy-method is executed, all spawned threads of Camel are stopped / vanished. There is also no log entry, that some orphaned threads exist when undeploying the app. So I don’t know, what's the mistake within this class. What would be the right way to clean up the ThreadLocal variable? Just stopping the threads didn’t seem to clean it up properly. Greetings, Thomas --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org