这篇文章,主要解决一下疑惑:
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是以单例模式一直存在的。

  • 大小: 18.7 KB
  • 大小: 15.9 KB
  • 大小: 26.8 KB
  • 大小: 26.4 KB
  • 大小: 39.3 KB
  • 大小: 26.2 KB
  • WeakReferenceTest.rar (7.6 KB)
http://liuinsect.iteye.com/blog/1827012

转载于:https://www.cnblogs.com/softidea/p/4819866.html

ThreadLocal是否会引发内存泄露的分析 good相关推荐

  1. 使用ThreadLocal不当可能会导致内存泄露

    使用ThreadLocal不当可能会导致内存泄露 基础篇已经讲解了ThreadLocal的原理,本节着重来讲解下使用ThreadLocal会导致内存泄露的原因,并讲解使用ThreadLocal导致内存 ...

  2. Android使用Handler造成内存泄露的分析及解决方法

    Android使用Handler造成内存泄露的分析及解决方法 参考文章: (1)Android使用Handler造成内存泄露的分析及解决方法 (2)https://www.cnblogs.com/xu ...

  3. 关于Android 的内存泄露及分析

    博客园 首页 新随笔 联系 管理 订阅 随笔- 137  文章- 6  评论- 145  关于Android 的内存泄露及分析 一. Android的内存机制 Android的程序由Java语言编写, ...

  4. java thread 内存泄露_Java ThreadLocal 内存泄露问题分析及解决方法。

    前言 在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露.强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这 ...

  5. 一文搞懂ThreadLocal及相关的内存泄露问题

    首先,看一张整体的结构图,来帮助理解 什么是ThreadLocal ThreadLocal用于创建线程局部变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副 ...

  6. java 代码 内存泄露_如何用Java编写一段代码引发内存泄露

    Q:刚才我参加了面试,面试官问我如何写出会发生内存泄露的Java代码.这个问题我一点思路都没有,好囧. A1:通过以下步骤可以很容易产生内存泄露(程序代码不能访问到某些对象,但是它们仍然保存在内存中) ...

  7. ThreadLocal可能引起的内存泄露

    threadlocal里面使用了一个存在弱引用的map,当释放掉threadlocal的强引用以后,map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露. 最好 ...

  8. 我对ThreadLocal的一些理解 内存泄露啥的

    1. 什么是ThreadLocal ThreadLocal提供了线程的局部变量,每个线程都可以通过set()和get()来对这个局部变量进行操作,但不会和其他线程的局部变量进行冲突,实现了线程的数据隔 ...

  9. ThreadLocal巨坑!内存泄露只是小儿科

    本文将会详细总结 ThreadLocal 容易用错的三个坑: 内存泄露 线程池中线程上下文丢失 并行流中线程上下文丢失 内存泄露 由于 ThreadLocal 的 key 是弱引用,因此如果使用后不调 ...

最新文章

  1. Python游戏开发,pygame模块,Python实现过迷宫小游戏
  2. mysql数字转换中文版_MYSQL字符数字转换
  3. 影响JavaScript应用可扩展性因素
  4. [Catalan数三连]网格有趣的数列树屋阶梯
  5. 分布式之系统底层原理
  6. TCP/IP五层模型(五层因特网协议栈)||| OSI参考模型|||数据的封装与解封装
  7. Struts2后台使用Request和Session方法
  8. paip.ollydbg 设置c++ qt API断点总结
  9. break用于什么场景python_break语句陷入循环
  10. Centos网络管理(五)-Bonding、网络组和网桥
  11. Power of Four(Leetcode 342)
  12. abb变频器580系列改中文_ABBACS580一01变频器选择使用语言错误后怎么办?
  13. ITIL 4知识系列之ITIL4的设计框架解析
  14. IP寻址与子网划分网管员要知道什么
  15. 高数复习(1)--曲线切向与曲面法向的理解
  16. PaysApi第三方支付接口的接入与使用 React前端SSM后端
  17. 20190919-5 代码规范
  18. python环境是什么_三分钟了解什么是Python?python环境搭建
  19. java error while loading shared libraries: libjli.so: cannot open shared object file
  20. 世界上第一个bug的发现者——被誉为“COBOL 之母”的葛丽丝 · 霍普。

热门文章

  1. 使用WebEx录制视频并转换为MP4
  2. POCO:InvalidOperationError:Mapping and metadata information could not be found for Entity Type
  3. Spring Boot2.0之整合Redis
  4. codevs 1472 体检
  5. We Chall-Prime Factory-Writeup
  6. 网络编程中的大端和小端
  7. TinyXml高速入口(一)
  8. 工厂方法模式--结合具体例子学习工厂方法模式
  9. java 报文请求_http 请求报文和响应报文编写 (java socket实例)
  10. linux vi 强制退出_linux的编辑大法