我一直在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()
会解决这个问题吗?我不明白。
答案 0 :(得分:1)
说明不正确:
导致泄漏是因为我们有一个ThreadLocal实例的自定义类
那部分是错的。 Thread类中的ThreadLocalMap使用weakReferences作为键,因此threadLocal实例是否为自定义类并不重要。我用我的自定义ThreadLocal类测试了它,并且没有内存泄漏。
,也是绑定到Thread的值的自定义类。
这是对的。对于值,线程不使用弱引用,所以如果一个值是一个自定义类,它将阻止它的类加载器被垃圾收集,这将导致该类加载器加载的所有类保留在内存中,直到从线程池中删除线程。