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?开发者_C百科 Will the code in the run() method still be able to resolve classes from my application?
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.
精彩评论