首页 > 系统相关 >ThreadLocal是否会引发内存泄露的分析 good

ThreadLocal是否会引发内存泄露的分析 good

时间:2022-12-19 15:32:37浏览次数:73  
标签:good ThreadLocalMap ThreadLocal 内存 key null 引用

这篇文章,主要解决一下疑惑:

1. ThreadLocal.ThreadLocalMap中提到的弱引用,弱引用究竟会不会被回收?

2. 弱引用什么情况下回收?

3. JAVA的ThreadLocal和在什么情况下会内存泄露?

 

带着这些疑问,自己模拟了一下ThreadLocal.ThreadLocalMap的结构,先展示下自己涉及的结构:


自己实现一个simple的ThreadLocalMap,里面用一个entry用来存放由自己模拟的ThreadLocal调用set方法set进去的值。

并且和JDK的ThreadLocalMap一样里面Entry对象的key用weakReference封装。

 

Main方法如下:


  

 

设置运行参数:

-verbose:gc  

 

看输出结果:


这里我已经模拟出了内存泄露的问题,可以看到FULL GC以后,内存还是被占用,且仔细观察可以看到,这个map中的Key已经有为null了。
换句话说你通过Key已经不能获取到value了,当然map.get(null)也是可以的,
不过JAVA里的ThreadLocal不会这么去做,因为Map中key==null的元素可能不唯一。

从我的Main方法中可以看到,我有th=null的操作,但是还是有内存泄露,原因稍后分析。
但有一点可以确定:th=null在这里不能如我们想象的将ThreadLocal th 的引用释放掉后,里面的key,value对象也释放,可能会有疑问我这里持有了ThreadLocalMap的引用tm所以不会回收,但实际上,手动设置JAVA的ThreadLocal为null时,当前线程任然持有ThreadLocalMap的引用,所以不会回收我这里和JAVA是类似的。

 

回到刚开始提出的3个问题,一一解答:

1. ThreadLocal.ThreadLocalMap中提到的弱引用,弱引用究竟会不会被回收?

     会被回收,如上图所示。key 已经有null的情况了。第一个Key不为null,原因在第二点。在经历过FULL GC后 所有的key都被回收了。

2. 弱引用什么情况下回收?

     弱引用在GC(包括MinitorGC和Full GC)时,被扫描到就会被回收,但是有一个前提,该弱引用在外部没有被引用到(这个时候外部的引用等于强引用)。

     换句话说,如果我main方法中持有一个key的引用,哪怕他put进Map后被设置为弱引用的,也不会被回收。见下图:


 


GC 日志:


 

     

3. JAVA的ThreadLocal和在什么情况下会内存泄露?

   答案是不会,原因如下图,在我们调用ThreadLocal.set()的时候,会做一个将Key== null 的元素清理掉的工作,具体做法是:

     第一步:ThreadLocalMap 拿threadLocalHashCode与长度减一相与,求出哈希表的位置下图中的 i 。

     第二步:编列Entry,如果找到key相等的,覆盖原值! 或者找到key==null的,将值set进去,并且将遍历时路过的key==null的元素和他的value都置为null,,释放内存。

     第三步:最后一个if条件时,做rehash的动作,即:将Entry里的元素重新计算一下Hash值,放到合适的位置去,猜想是为了加快下次访问的速度。



 

总结:

     从这里看出,JAVA的ThreadLocal对Key使用到了弱引用,但是为了保证不再内存泄露,在每次set.get的时候主动对key==null的entry做遍历回收。

     虽然不会造成内存泄露,但是因为只有在每次set,get的时候才会对entry做key==null的判断,从而释放内存,所以可能使大对象在内存中存活很长一段时间,从而占用内存。

     所以,我们在使用完ThreadLocal里的对象后最好能手动remove一下,或者至少调用下ThreadLocal.set(null)。

     值得注意的是ThreadLocal中的key是当前当前ThreadLocal自己,就像上面模拟的外部持有强引用的情况,ThreadLocal.ThreadLocalMap中的key==null情况很少出现,因为,大部分情况ThreadLocal是以单例模式一直存在的。

 

 



标签:good,ThreadLocalMap,ThreadLocal,内存,key,null,引用
From: https://blog.51cto.com/u_15147537/5952716

相关文章

  • 常见的内存溢出与解决办法
    引起内存溢出的原因有很多种,常见的有以下几种:1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;......
  • 百度工程师带你探秘C++内存管理(ptmalloc篇)
    作者|daydreamer前篇《​​探秘C++内存管理(理论篇)​​》主要介绍了LinuxC++程序内存管理的理论基础,本文作为系列文章《探秘C++内存管理》的第二篇,将会探讨经典内存管理器......
  • java程序内存泄漏的定位与分析
    1、为什么会发生内存泄漏​​Java​​ 如何检测内在泄漏呢?我们需要一些工具进行检测,并发现内存泄漏问题,不然很容易发生down机问题。编写java程序最为方便的地方就是我们不......
  • Java核心实操:内存溢出 实战、内存泄漏实战
    文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面......
  • 如何确保不使用动态内存
      在许多嵌入式应用程序中,内存分配必须是静态的,而不是动态的。意味着在应用程序中不应使用对malloc()或free()等内容的调用,因为它们可能会在运行时失败(内存不足、堆碎片)......
  • 解决Mac在Chrome播放视频时缓存写入ssd过猛问题,内存交换直彪
    都知道mac的ssd焊死在主板上ssd的报废意味着你又能换新mac了这些天我发现chrome挂直播看世界杯时候内存占用异常的高赶忙发现在浏览器播放视频时写入ssd的速度直线飙升......
  • 内存和ssd速度差距(diy从入门到放弃固态能取代内存吗)
    原文地址:https://mpc.7buzou.com/article/5745.html虽然内存和SSD都是存储产品,但两者的待遇却完全不一样:8G内存可以轻松卖到200元的价格,而200元可以买到256GB的SSD,价格差......
  • 一次性能调优记录:压测报错out of memory内存溢出【杭州多测师_王sir】【杭州多测师】
    一次性能调优记录:压测报错out of memory内存溢出1、首先这是一段压测的报错日志截图2、服务器的配置还不错,执行机全64核以上,运存256g以上,服务器80核,512g,所有机器线程数......
  • C#内存复制性能分析
    staticclassProgram{[DllImport("kernel32.dll",EntryPoint="CopyMemory",SetLastError=false)]publicstaticexternvoidCopyMemo......
  • 利联科技:DDR3和DDR4内存有什么区别
    内存是计算机中非常重要的硬件,计算机中所有程序的运行都是在内存中进行的,并且它是计算机与处理器沟通的桥梁,因此内存的性能对计算机的影响非常大。只要计算机在运行,处理器就......