我正在尝试清理有关由于创建自己的线程而导致的内存泄漏的Tomcat警告。 http://wiki.apache.org/tomcat/MemoryLeakProtection建议在启动线程之前先调用myThread.setContextClassLoader(null)
。
此电话的含义是什么? run()方法中的代码是否仍然能够解析应用程序中的类?
最佳答案
是的,它会的。 Thread.getContextClassLoader()
是一种用于通用框架从类加载器树进一步加载资源的机制。
以Tomcat的类加载器层次结构为例。
Bootstrap
|
System
|
Common
/ \
Webapp1 Webapp2 ...
Servlet或JSP框架位于
Common
类加载器中。如果这些框架之一是要从Webapp1
加载类路径资源,则可以尝试:getClass().getResource("/some/resource/in/webapp1"); // fail
但是由于类加载机制仅委托调用了类加载器链,所以这将失败。这意味着所有需要加载资源的框架都会:
Thread.currentThread().getContextClassLoader().getResource("/some/resource/in/webapp1");
每当线程在该上下文中执行时,servlet容器都将确保它是
Webapp1
类加载器。因此,线程的上下文类加载器实际上是框架从“错误方向”加载类的一种方式。当您产生一个新线程时,默认情况下,该线程将获取其父级(您的
Webapp1
类加载器)的上下文类加载器。因此,如果您停止Webapp1
,则tomcat应该能够对该Web应用程序进行GC,但只要对Webapp1
类加载器有任何引用,它就无法这样做-因此发出警告。Good article about context class loaders。