ThreadLocal 详解(三)内存泄露原因,以及强弱引用

1、ThreadLocal内存泄漏

在Threadlocal的内部静态类中Entry将Threadlocal作为一个key,值作为value保存,他继承WeakReference,super(k),代表了Threadlocal对象是一个弱引用;

java 复制代码
static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

内存泄漏原因:

  • 没有手动删除这个Entry,调用remove()
  • CurrentThread当前线程仍然在运行

对于第一点:只有使用完Threadlocal,调用其remove()删除对应对的Entry,可以避免内存泄漏;

对于第二点:

  • ThreadlocalMap作为Thread的一个变量,只要Thread运行,那么ThreadlocalMap就不会被清理掉。
  • 通过上面源码可以看出,Threadlocal运行在一个方法中,在虚拟机栈的局部变量表中某个slot上,指向了内存空间中该Threadlocal对象,假设调用了get()方法后,ThreadlocalMap中的一个Entry指向了Threadlocal实例,且是弱引用,该方法执行完成,虚拟机栈释放。此时只有ThreadLocalMap中的一个Entry指向ThreadLocal对象
  • 此时发生GC,根据弱引用的特点,如果一个对象只有弱引用,该对象将被回收,此时ThreadlocalMap中出现一个entry(null,Entry)
  • ThreadLocalMap中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。

总结:由于ThreadLocalMap 的生命周期跟 Thread 一样长,对于重复利用的线程来说,如果没有手动删除(remove()方法)对应 key 就会导致entry(null,value)的对象越来越多,从而导致内存泄漏.

2、为什么不将key设置为强引用

那么为什么ThreadLocalMap的key要设计成弱引用呢?其实很简单,如果key设计成强引用且没有手动remove(),那么key会和value一样伴随线程的整个生命周期。假设在业务代码中使用完ThreadLcoal,ThreadLocal ref被回收了,但是ThreadLocalMap强引用了Threadlocal(Key就是ThreadLocal),造成了ThreadLocal无法被回收。在没有手动回收Entry以及CurrentThread依然运行的前提下,始终有强引用链 CurrentThread Ref -> CurrentThread -> ThreadLocalMap -> entryEntry就不会被回收( Entry中包括了ThreadLocal实例和value), 导致Entry内存泄漏

结尾:喜欢的朋友点个赞吧!!!

相关推荐
2602_9599609210 小时前
电商大厂Java面试:从Spring Boot、JPA、微服务到Redis、Kafka、Spring Security与监控,谢飞机的爆笑三轮问答
java·jvm·spring boot·redis·面试题
一水10 小时前
AI 时代审查思维:审查第一篇
java·jvm·数据库·spring
それども18 小时前
JVM MetaspaceSize 参数作用
jvm
java_upp1 天前
JVM内存溢出和内存泄漏的区别及排查方法
jvm·内存泄漏·内存溢出
城管不管1 天前
MySQL 慢查询完整排查
java·服务器·jvm·数据库·mysql·spring·面试
mister_guo2 天前
JVM 内存管理原理及生产配置实战:从“参数能启动”到“内存可控”
java·jvm
名字还没想好☜3 天前
Go 的 strings.Builder 实战:拼接性能、Grow 预分配与何时该用 bytes.Buffer
java·jvm·后端·golang·go
wear工程师3 天前
Java 类初始化到底何时触发?别把加载、连接和 static 执行混在一起
java·jvm
程序员雷欧3 天前
线上频繁触发各种 GC 的原因排查与处理指南
java·jvm·算法
wuminyu4 天前
JVM利用io_uring优化堆外内存性能原理剖析
java·linux·c语言·jvm·c++