症结是由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。
栗子如下:
class MyCounter {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
class MyThreadLocal extends ThreadLocal{
}
public class HelloServlet extends HttpServlet {
private static MyThreadLocal myThreadLocal = new MyThreadLocal();
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
MyCounter counter = myThreadLocal.get();
if (counter == null) {
counter = new MyCounter();
myThreadLocal.set(counter);
}
}
}
这个栗子会导致内存泄露,咱们分析代码可以看出,使用static的ThreadLocal,延长了ThreadLocal的生命周期,导致myThreadLocal的生命周期跟Servlet类的生命周期一样长,意味着myThreadLocal不会被回收,弱引用形同虚设,所以当前线程无法通过ThreadLocalMap的防护措施清除counter的强引用。