setContextClassLoader含义

yka*_*ich 3 java multithreading tomcat java-ee

我正在尝试清理由于创建自己的线程而导致内存泄漏的Tomcat警告.http://wiki.apache.org/tomcat/MemoryLeakProtection建议我myThread.setContextClassLoader(null)在启动线程之前调用.

这次电话的含义是什么?run()方法中的代码是否仍然能够从我的应用程序中解析类?

Mar*_*ten 11

是的,它会的.这Thread.getContextClassLoader()是一种通用框架从类加载器树中进一步加载资源的机制.

以Tomcat的类加载器层次结构为例.

      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ... 
Run Code Online (Sandbox Code Playgroud)

servlet或JSP框架驻留在Common类加载器中.如果其中一个框架要加载类路径资源Webapp1,他们可以尝试:

getClass().getResource("/some/resource/in/webapp1"); // fail
Run Code Online (Sandbox Code Playgroud)

但是由于类加载机制仅委托调用类加载器链,这将失败.这意味着需要加载资源的所有框架都会:

Thread.currentThread().getContextClassLoader().getResource("/some/resource/in/webapp1");
Run Code Online (Sandbox Code Playgroud)

并且servlet容器确保Webapp1只要线程在该上下文中执行,这就是类加载器.因此,线程的上下文类加载器实际上是框架从"错误的方向"加载类的一种方式.

当您生成一个新线程时,该线程默认获取其父级(您的Webapp1类加载器)的上下文类加载器.如果你因此停止了Webapp1,那么tomcat应该能够对那个webapp进行GC,但是只要有任何引用留给Webapp1类加载器就不能这样做- 因此警告.

关于上下文类加载器的好文章.