自定义 ThreadLocal 类 的 ThreadLocal 泄漏说明
Explanation of ThreadLocal leaks for custom ThreadLocal classes
我一直在阅读 article 关于 Tomcat 中 ThreadLocal 泄漏的文章。第一个示例包含此代码:
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();
}
}
它说所有 类 都驻留在 webapp 中。然后它概述了以下对类加载器(不是ThreadLocal)泄漏的解释,我不明白:
If the LeakingServlet is invoked at least once and the Thread that
served it is not stopped, then we created a classloader leak !
The leak is caused because we have a custom class for the ThreadLocal
instance, and also a custom class for the value bound to the Thread.
Actually the important thing is that both classes were loaded by the
webapp classloader.
ThreadLocal 泄漏的解释很糟糕。如果为请求提供服务的线程没有停止,我们怎么会有 ThreadLocal 泄漏(实际上文章说类加载器泄漏)?这是否意味着,如果 Thread 是 Tomcat 线程池的一部分并且由于 MyThreadLocal.remove()
尚未关闭,那么 MyCounter / MyThreadLocal 的 webapp 类加载器不能被垃圾收集,因为 Thread 已返回到池中?调用 MyThreadLocal.remove()
会解决这个问题吗?没看懂。
解释不正确:
The leak is caused because we have a custom class for the ThreadLocal instance
那部分是错误的。 Thread class 中的 ThreadLocalMap 使用 weakReferences 作为键,因此 threadLocal 实例是否是自定义实例并不重要 class。我用我的自定义 ThreadLocal class 测试了它,没有内存泄漏。
, and also a custom class for the value bound to the Thread.
这是正确的。对于值线程不使用弱引用,因此如果值是自定义 class 将阻止它的 class 加载程序被垃圾收集,这将导致所有 class 由该 [=18] 加载=] 加载程序保留在内存中,直到线程从线程池中删除。
我一直在阅读 article 关于 Tomcat 中 ThreadLocal 泄漏的文章。第一个示例包含此代码:
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();
}
}
它说所有 类 都驻留在 webapp 中。然后它概述了以下对类加载器(不是ThreadLocal)泄漏的解释,我不明白:
If the LeakingServlet is invoked at least once and the Thread that served it is not stopped, then we created a classloader leak !
The leak is caused because we have a custom class for the ThreadLocal instance, and also a custom class for the value bound to the Thread. Actually the important thing is that both classes were loaded by the webapp classloader.
ThreadLocal 泄漏的解释很糟糕。如果为请求提供服务的线程没有停止,我们怎么会有 ThreadLocal 泄漏(实际上文章说类加载器泄漏)?这是否意味着,如果 Thread 是 Tomcat 线程池的一部分并且由于 MyThreadLocal.remove()
尚未关闭,那么 MyCounter / MyThreadLocal 的 webapp 类加载器不能被垃圾收集,因为 Thread 已返回到池中?调用 MyThreadLocal.remove()
会解决这个问题吗?没看懂。
解释不正确:
The leak is caused because we have a custom class for the ThreadLocal instance
那部分是错误的。 Thread class 中的 ThreadLocalMap 使用 weakReferences 作为键,因此 threadLocal 实例是否是自定义实例并不重要 class。我用我的自定义 ThreadLocal class 测试了它,没有内存泄漏。
, and also a custom class for the value bound to the Thread.
这是正确的。对于值线程不使用弱引用,因此如果值是自定义 class 将阻止它的 class 加载程序被垃圾收集,这将导致所有 class 由该 [=18] 加载=] 加载程序保留在内存中,直到线程从线程池中删除。