ThreadLocal内存泄露原因,如何避免

内存泄露为程序在申请内存后,无法释放已经申请的内存空间,一次内存泄露可以忽略,但是内存泄露堆积后果很严重,无论多少内存迟早被用光。

不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。

强引用:使用最普遍的引用(new), 一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使得程序异常终止,也不会回收这个对象。

如果想取消强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。

弱引用:JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在Java中,用java.lang.ref.WeakReference类来表示,可以再缓存中使用弱引用。

ThreadLocal的实现原理,每一个Thread维护一个ThreadLocalMap,key为弱引用的Thread实例,value为线程变量的副本。

ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null,而value还存在着强引用,只有当thread线程退出以后value的强引用链才会断掉,但如果当前线程迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链。

如果ThreadLocalMap的key使用强引用,因为ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄露。

当ThreadLocalMap的key为弱引用回收ThreadLocal对象时,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。当key为null时,在下一次ThreadLocalMap调用set(),get(),remove()方法时就会清除value值。

因此,ThreadLocal内存泄露的根源:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄露,而不是因为弱引用。

ThreadLocal正确的使用方法

(1)每次使用完ThreadLocal都调用它的remove()方法清楚数据

(2)将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到entry的value值,进而清除掉。

相关推荐
玄〤1 分钟前
Spring MVC 讲解:从初始化流程到请求参数与 JSON 处理全解析(黑马课程ssm笔记总结)(day5)
java·spring·json·mvc
廋到被风吹走3 分钟前
【Java】【JVM】垃圾回收深度解析:G1/ZGC/Shenandoah原理、日志分析与STW优化
java·开发语言·jvm
xrkhy4 分钟前
Java全栈面试题及答案汇总(3)
java·开发语言·面试
SunnyDays10117 分钟前
Java 高效实现 CSV 转 PDF
java·csv转pdf
隐形喷火龙9 分钟前
SpringBoot 异步任务持久化方案:崩溃重启不丢任务的完整实现
java·spring boot·后端
我是koten10 分钟前
K8s启动pod失败,日志报非法的Jar包排查思路(Invalid or corrupt jarfile /app/xxxx,jar)
java·docker·容器·kubernetes·bash·jar·shell
WX-bisheyuange14 分钟前
基于Spring Boot的库存管理系统的设计与实现
java·spring boot·后端
YanDDDeat19 分钟前
【JVM】类初始化和加载
java·开发语言·jvm·后端
码农水水20 分钟前
阿里Java面试被问:单元测试的最佳实践
java·面试·单元测试
indexsunny20 分钟前
互联网大厂Java面试实战:Spring Cloud微服务与Redis缓存在电商场景中的应用
java·spring boot·redis·spring cloud·微服务·消息队列·电商