Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setContextClassLoader implications

I'm trying to clean up Tomcat warnings about memory leaks due to creating my own threads. http://wiki.apache.org/tomcat/MemoryLeakProtection proposes that I call myThread.setContextClassLoader(null) prior to starting the thread.

What is the implication of this call? Will the code in the run() method still be able to resolve classes from my application?

like image 461
ykaganovich Avatar asked Dec 21 '22 20:12

ykaganovich


1 Answers

Yes it will. The Thread.getContextClassLoader() is a mechanism for generic frameworks load resources from further down the class loader tree.

Take Tomcat's class loader hierarchy.

      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ... 

The servlet or JSP framework resides in the Common class loader. If one of these frameworks is to load a classpath resource from Webapp1, they could try:

getClass().getResource("/some/resource/in/webapp1"); // fail

But since class loading mechanics only delegates calls up the class loader chain, this would fail. This means that all frameworks that needs to load a resource instead do:

Thread.currentThread().getContextClassLoader().getResource("/some/resource/in/webapp1");

And the servlet container makes sure this is the Webapp1 class loader whenever the thread is executing in that context. So the thread's context classloader is effectively a way for frameworks to load classes from "the wrong direction".

When you spawn a new thread, that thread gets, by default the context class loader of its parent (your Webapp1 classloader). If you consequently stop Webapp1, tomcat is supposed to be able to GC that webapp, but is unable to do so as long as there's any reference left to the Webapp1 class loader - hence the warning.

Good article about context class loaders.

like image 84
Martin Algesten Avatar answered Dec 24 '22 11:12

Martin Algesten