Java的强引用、软引用、弱引用、虚引用

1强引用

Object o = new Object()的赋值 o的引用就是new出来的这个Object

2软引用

通过SoftReference创建的引用对象就是软引用

软引用对象会在内存不足进行GC的时候会被回收

3弱引用

通过WeakReference创建的对象就是弱引用

弱引用会在GC时被回收(全部GC还是YoungGC|MinorGC|FullGC)

3.1ThreadLocal内存泄露分析

经典应用ThreadLocal.ThreadLockMap.Entry的k是一个弱引用

image-20220116202518578

如图②中,ThreadLocalMap中的k是通过弱引用指向ThreadLocal对象,在图①中的local是一个指向ThreadLocal的强引用,

如果k是强引用的话,当local引用被回收,但是此时k依然引用着ThreadLocal对象,如图③Thread类中的threadLocals,如果对应的线程不被回收,则ThreadLocalMap会被一直引用着,于此同时Entry中的k也不会被回收,因为local被回收,k将无法被访问到,但是如果是强引用,k随着线程一直存在,不会被回收,ThreadLocal对象也会一直存在,但是无法访问到,会导致内存泄露,使用弱引用会在k没有其他强引用的引用后被回收.(当然线程被回收后,k和value也会随着线程的回收被回收掉,但是对于服务器中的监测、网络线程等长期存在的线程强引用则会导致内存的泄露)

3.2为什么ThreadLocal依然存在内存泄露的问题

图①的local被回收之后,ThreadLocalMap中的k对应的ThreadLocal对象也会被回收,既然k会变成null,此时会导致value无法被访问到,但是由于线程没有被回收,所以Thread中的threadLocals一直存在,导致value无法被回收,因此还是存在内存泄露的问题.

如图②中Entry的构造函数中,调用WeakReferance的构造方法,并将k传入,将k作为弱引用.

3.3为什么当前依旧存在内存泄露的问题呢?

既然当前是弱引用对象,即图①的local被回收之后,ThreadLocalMap中的k对应的ThreadLocal对象也会被回收,既然k被回收,那么会导致value无法被访问到,因此还是存在内存泄露的问题.

3.4如果解决内存泄露问题

在使用完ThreadLocal存储的内容,后调用ThreadLocal中的remove()方法,手动将value变为null

4虚引用

虚引用也称幽灵引用幻影引用,通过PhantomReference对象创建

如果一个对象的强引用或者软引用消失,那么这个对象会被GC回收,回收前调用其finalize()方法,如果调用过finalize()方法后还没有被回收掉,这个对象就会成为一个虚引用对象.

虚引用的值永远访问不到,get()方法永远返回null

虚引用的创建需要用到一个Queue,可以通过queue来检查是否有弱引用被回收,当使用DirectByteBuffer操作堆外的是否,需要来对堆外回收内存,使用虚引用来监听对象被回收,对象回收后,来进行堆外内存的回收

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想写代码~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值