ThreadLocal内存泄露问题

80 阅读1分钟

Thread类中有一个threadLocals变量,类型为ThreadLocalMap

public class Thread {
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

ThreadLocalMap对key的引用是弱引用,对value的引用是强引用。

假设我们在一个方法内定义了一个ThreadLocal局部变量,在方法运行过程中,这个ThreadLocal变量同时持有2个引用:

  1. java虚拟机栈的局部变量表对ThreadLocal变量的强引用

  2. ThreadLocalMap对ThreadLocal变量的弱引用

单条引用链的可达性以最弱的引用类型决定,多条引用链的可达性以最强的引用类型决定,因此方法运行过程中,ThreadLocal变量拥有强引用,不会被垃圾回收。

当方法运行结束后,ThreadLocal变量仅剩ThreadLocalMap对它的虚引用,随时可能被垃圾回收掉。

当ThreadLocal对象被回收之后,ThreadLocalMap里key为null,value不为null,但是只要Thread类还在运行,ThreadLocalMap对value的强引用就有效,因此value不会被自动回收。

因此,当我们使用完ThreadLocal之后,需要手动remove掉,remove方法里会把value设置为null。


为什么ThreadLocaMap对value的引用不做成弱引用?

  • key,除了ThreadLocaMap的弱引用,可能还会有ThreadLocal的强引用(方法还没运行结束时),只要后者还在,Key就不会被回收。
  • value只有ThreadLocaMap的引用,如果value是弱引用,那随时会被回收,ThreadLocal就没法用了。