ThreadLocal尾篇:ThreadLocal内存泄漏到底因为啥

简介: ThreadLocal尾篇:ThreadLocal内存泄漏到底因为啥

最近看ThreadLocal内存泄漏这块,网上说法很多。呼声最多的是因为弱引用导致的内存泄漏。


为啥内存泄漏


image.png


1.ThreadLocal什么情况下被回收

ThreadLocalThreadLocalMap中是以一个弱引用身份被Entry中的Key引用,当GC发生时,ThreadLocal会不会被回收?

这里就用到引用的知识点了。 在java的四种引用讲过。当一个对象被强引用指向时(这里指可达)。垃圾回收器不会回收他。

例如

ThreadLocal threadlocal1 = new ThreadLocal();
threadlocal1.set("测试");

ThreadLocal对象此时有两种索引指向的。

  • 强引用:threadlocal1对应图中【1】
  • 弱引用:Key(WeakReference(threadlocal1))对应图中的【2】

所以GC发生时,堆内ThreadLocal对象不会被回收。

但是当我们把threadlocal1 =null;断开强引用时,此时ThreadLocal对象只有一个弱引用,那么GC发生时,ThreadLocal对象被回收了,Entry变成了一个key为null的Entry。也叫脏Entry

特点是:

  • key为null,value不能被应用程序访问到,因为我们已经没有引用到他的引用了
  • Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value链存在,当前线程迟迟不结束(例如线程池),但不能被使用,成了脏数据,造成了内存泄漏。

看上去好像真是软引用造成的内存泄漏。


2.为啥用弱引用

那换做强引用分析:ThreadLocal对象被两个强引用指向

  • 强引用: threadlocal1
  • 强引用: Entry.key

当我们断开程序中的强引用 threadlocal1时。ThreadLocal对象仍然被强引用Entry.key指向,不会回收,这就造成,ThreadLocal对象与 value都成为了脏数据。


对比这两种情况:不管软引用还是强引用,都可能出现内存泄漏问题,弱引用反而将内存泄漏的程度降低

利用弱引用的Entry会有key为null这个特征,可以识别哪些是不用的数据,进行清理操作,弱引用 反而提高了ThreadLocal的安全性。

事实上当调用ThreadLocalget(),set(),reomve()方法,都会清除掉线程ThreadLocalMap中所有Entry中Key为null的Value,并将整个Entry设置为null,利于下次内存回收。

3.泄漏的真正原因

所以:ThreadLocal内存泄漏的真正原因:

  1. ThreadLocalMap的生命周期跟Thread一样长,如果线程池不退,例如线程池,可能造成内存泄漏
  2. 使用完没有及时清理,不再调用get()、set()、remove()对脏Entry进行清理

这才是造成内存泄漏的真正原因。


总结:


使用完及时remove,才是最正宗的使用方式

如有错误,请告知,共同学习。


相关文章
|
4月前
|
存储 Java 数据挖掘
来聊聊ThreadLocal内存泄露分析
来聊聊ThreadLocal内存泄露分析
|
5月前
|
机器学习/深度学习 安全 Java
从源码深入详解ThreadLocal内存泄漏问题
从源码深入详解ThreadLocal内存泄漏问题
81 0
|
6月前
|
存储 安全 Java
表妹和我纠结,线上系统因为一个ThreadLocal直接内存飙升
大家对于ThreadLocal这一个都应该听说过的吧,不知道大家对于这个掌握的怎么样了已经 这不,我那爱学习的表妹不知道又从哪里听来了这个技术点,回家就得意洋洋地给我说,表哥,我今天又学会了一个技术点ThreadLocal
|
7月前
|
存储 Java
【ThreadLocal的内存泄露问题】
【ThreadLocal的内存泄露问题】
|
8月前
|
Java
ThreadLocal内存泄露分析
ThreadLocal内存泄露分析
57 0
|
8月前
|
存储 机器学习/深度学习 缓存
我惊了!!!ThreadLocal 源码存在内存泄露的 Bug!!!
我惊了!!!ThreadLocal 源码存在内存泄露的 Bug!!!
|
8月前
|
存储 缓存 Java
ThreadLocal真的会造成内存泄漏吗?
ThreadLoca在并发场景中,应用非常多。前几天有位小伙伴问我一个问题,说ThreadLocal是不是真的会造成内存泄漏?今天给大家做一个分享,个人见解,仅供参考。如果大家有其他见解可以在评论区讨论。
106 0
|
10月前
|
Java
【Java面试】说说你对ThreadLocal内存泄漏问题的理解
【Java面试】说说你对ThreadLocal内存泄漏问题的理解
89 0
|
10月前
|
缓存 监控 Java
【Java面试】Java中都有那些引用类型?(关于弱引用是如何解决ThreadLocal内存泄漏问题)
【Java面试】Java中都有那些引用类型?(关于弱引用是如何解决ThreadLocal内存泄漏问题)
66 0
|
10月前
|
Java
ThreadLocal-内存泄露问题
在使用ThreadLocal时,如果没有及时清理ThreadLocal变量,就可能会导致内存泄漏问题。这是因为ThreadLocalMap中的Entry对象持有了对ThreadLocal对象的强引用,而ThreadLocal对象又持有了对变量副本的引用。如果没有手动调用remove()方法来清理ThreadLocal变量,那么Entry对象和变量副本就会一直存在于ThreadLocalMap中,无法被垃圾回收。
62 0