08-内存泄漏_key强OR弱引用的情况

本文探讨了ThreadLocal中内存泄漏与弱引用的关系。内存泄漏通常发生在动态分配的堆内存未被释放,而弱引用在Java中允许GC回收对象。ThreadLocalMap使用弱引用作为key,当ThreadLocal为null时,弱引用key会在下次调用set、get或remove时清除value,降低内存泄漏风险。避免内存泄漏的关键是及时调用remove或确保线程结束。
摘要由CSDN通过智能技术生成

弱引用和内存泄漏

有些程序员在使用ThreadLocal的过程中会发现有内存泄漏的情况发生,就猜测这个内存泄漏跟Entry中使用了弱引用的key有关系。这个理解其实是不对的。

我们先来回顾这个问题中涉及的几个名词概念,再来分析问题。

1、内存泄漏相关概念

  • Memory overflow:内存溢出,没有足够的内存提供申请者使用。
  • Memory leak:内存泄漏是指程序中动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄漏的堆积终将导致内存溢出。

2、弱引用相关概念

Java中的引用有4种类型:强、软、弱、虚。当前这个问题主要涉及到强引用和弱引用:

  • 强引用(Strong Reference),就是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还“活着”,垃圾回收器就不会回收这种对象。
  • 弱引用(WeakReference),垃圾回收器一旦发现了只具备有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

3、如果key使用强引用

假设ThreadLocalMap中的key使用了强引用,那么会出现内存泄漏吗?

此时ThreadLocal的内存图(实线表示强引用)如下:

image.png

4、如果key使用弱引用

image.png

5、出现内存泄漏的真实原因

image.png

6、为什么使用弱引用

根据刚才的分析,我们知道了:无论ThreadLocalMap中的key使用哪种类型引用都无法完全避免内存泄漏,跟使用弱引用没有关系。

要避免内存泄漏有两种方式:

    1. 使用完ThreadLocal,调用其remove方法删除对应的Entry
    2. 使用完ThreadLocal,当前Thread也随之运行结束

相对第一种方式,第二种方式显然更不好控制,特别是使用线程池的时候,线程结束是不会销毁的。也就是说,只要记得在使用完ThreadLocal及时的调用remove方法,无论key是强引用还是弱引用都不会有问题。那么为什么key要用弱引用呢?

事实上,在ThreadLocalMap中的set/getEntry方法中,会对key为null(也即是ThreadLocal为null)进行判断,如果为null的话,那么是会对value置为null的。

这就意味着使用完ThreadLocal,CurrentThread依然进行的前提下,就算忘记调用remove方法,弱引用比强引用可以多一层保障:弱引用的ThreadLocal会被回收,对应的value在下一次ThreadLocalMap调用set、get、remove中的任一方法的时候会被清除,从而避免内存泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值