自定义ThreadLocal类的ThreadLocal泄漏的说明

时间:2017-12-20 12:32:30

标签: java tomcat thread-local

我一直在Tomcat的ThreadLocal漏洞上阅读此article。第一个示例包含此代码:

IsDuplicateOf

它表示所有类都驻留在webapp中。然后概述了类加载器(而不是ThreadLocal)泄漏的以下解释,我不明白:

  

如果至少调用一次LeakingServlet并且调用那个线程   服务它没有停止,然后我们创建了一个classloader泄漏!

     

导致泄漏是因为我们有一个ThreadLocal的自定义类   实例,以及绑定到Thread的值的自定义类。   实际上重要的是这两个类都被加载了   webapp classloader。

ThreadLocal泄漏的解释非常糟糕。如果服务请求的线程没有停止,我们怎么会有ThreadLocal泄漏(实际上文章说类加载器泄漏)?这是否意味着,如果Thread是Tomcat线程池的一部分并且由于public class MyCounter { private int count = 0; public void increment() { count++; } public int getCount() { return count; } } public class MyThreadLocal extends ThreadLocal<MyCounter> { } public class LeakingServlet extends HttpServlet { private static MyThreadLocal myThreadLocal = new MyThreadLocal(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { MyCounter counter = myThreadLocal.get(); if (counter == null) { counter = new MyCounter(); myThreadLocal.set(counter); } response.getWriter().println( "The current thread served this servlet " + counter.getCount() + " times"); counter.increment(); } } 尚未关闭,那么MyCounter / MyThreadLocal的webapp类加载器不能被垃圾收集,因为Thread被返回到池中?调用MyThreadLocal.remove()会解决这个问题吗?我不明白。

1 个答案:

答案 0 :(得分:1)

说明不正确:

  

导致泄漏是因为我们有一个ThreadLocal实例的自定义类

那部分是错的。 Thread类中的ThreadLocalMap使用weakReferences作为键,因此threadLocal实例是否为自定义类并不重要。我用我的自定义ThreadLocal类测试了它,并且没有内存泄漏。

  

,也是绑定到Thread的值的自定义类。

这是对的。对于值,线程不使用弱引用,所以如果一个值是一个自定义类,它将阻止它的类加载器被垃圾收集,这将导致该类加载器加载的所有类保留在内存中,直到从线程池中删除线程。