ThreadLocal中的key:cache
ThreadLocal<String> cache = ThreadLocal.withInitial(() -> null);
从简写源码中可以看出ThreadLocal中的val引用链
Thead——>ThreadLocal.ThreadLocalMap.Entry——>Object val
所以只要当前线程还存在 val就不会被gc回收
而key只存在一个软引用和我们创建threadLocal对象时的cache引用
当cache不在引用时 并且发生gc key会被回收 而val依然存在 就发生了内存泄漏
class Thead {
ThreadLocal.ThreadLocalMap threadLocals;
class ThreadLocal{
class ThreadLocalMap {
class Entry extends WeakReference<java.lang.ThreadLocal<?>> {
Object value;
Entry(java.lang.ThreadLocal<?> k, Object v) {
// k被挂上一个弱引用
super(k);
// v被挂上value的强引用
value = v;
}
}
}
}
}
下面模拟内存泄漏 创建一个Cache类
class Cache {
private ThreadLocal<String> threadLocal;
public void set(String val) {
if (threadLocal == null) {
threadLocal = ThreadLocal.withInitial(() -> null);
}
threadLocal.set(val);
}
}
测试类
public class Demo {
public static void main(String[] args) {
// 当set方法执行完后cache对象会在gc时被回收 它的属性threadLocal也同样
set("trf");
// System.gc();
Thread thread = Thread.currentThread();
}
public static void set(String val) {
new Cache().set(val);
}
}
对以上过程进行调试
未进行gc时 可以发现key和val都还存在
进行gc后key被回收 而val依然存在 因为它被thead所间接引用 这时在mian方法将无法再删除val 并且只要线程还存在val将一直在内存中