Java四大引用:强、软、弱、虚,彻底搞懂内存管理!

01 引言

在Java的世界里,对象的生死不仅由代码决定,更由引用的类型掌控。对象产生需要内存去支撑,而在内存固定的情况下,对象的存活的生命周期对于内存的管理至关重要。不使用的对象,垃圾回收器根据可达性分析、三色标记等不同的算法等默默回收着。

Java的这四大引用,也影响着垃圾回收器对垃圾回收的时机。理解这四种引用,可以更精确的控制对象的回收,也是你进阶高级开发的必经之路!

02 为什么需要不同的引用类型

Java的垃圾回收(GC)看似自动,但不当的对象引用会导致内存泄漏或OOM崩溃。细粒度的对对象的控制可以应用到不同的场景。通过四种引用类型,我们至少可以做到下面几点:

  • 精细化控制对象生命周期,实现对象的提前回收
  • 实现高效缓存,如图片缓存
  • 有效防止内存泄漏,如ThreadLocal
  • 感知对象回收事件

03 四大引用详解

不同的引用类型,受垃圾回收器回收的影响各不相同。

3.1 强引用

强引用(Strong Reference),默认的引用类型,也是最常见的。如果一个对象被强应用,这要这种引用还存在就不会被垃圾回收器回收。

// 强引用
Object objet = new Object();

其中object就是一个强引用的对象,不会被垃圾回收器回收。对象的一般都是在方法内进行的,所以其作用域只会在方法栈上,只有到强引用跳出了其作用域,也就是弹出方法栈,那么该引用就被在合适的时机被垃圾回收器回收。

从图中可以看到,方法内的垃圾回收并不会回收强引用的对象。

简单总结一下:

  • 特点:只要强引用存在,对象绝不会被GC回收
  • 风险obj = null手动释放前,即使内存不足也不会回收,可能引发OOM
  • 场景:日常开发中最常用的引用类型

3.2 软引用

软引用(Soft Reference),被称为内存敏感的安全气囊。如果一个对象被软引用,那么在JVM内存溢出之前,是不会被垃圾回收器回收的;只有到JVM内存不够时,才会被垃圾回收器回收这个对象。

软引用的对象需要借助java.lang.ref.WeakReference,实现对象的软引用。

可以看到,调用GC之后,并不会回收引用对象。

小结一下:

  • 特点:内存充足时保留对象;内存不足时优先回收
  • 回收时机:GC后发现内存仍不足 → 回收所有软引用
  • 场景:图片/数据缓存(Android中Glide的缓存机制)

3.3 弱引用

弱引用(Weak Reference),被称为随时消失的"临时工"。如果一个对象被弱引用,那么它的生命周期只能存活在下一次GC之前,只要GC启动,就会回收所有的弱引用对象。

弱引用的对象需要借助java.lang.ref.WeakReference,实现对象的弱引用。

可以看到,调用GC之后,弱引用对象就会被回收。

小结一下:

  • 特点:无论内存是否充足,下一次GC必然回收
  • 场景WeakHashMap实现临时缓存(Key被回收时自动移除Entry)

3.4 虚引用

虚引用(Phantom Reference),被称为对象回收的"墓碑"。虚引用是所有引用中最弱的一种,是无法直接获取到弱引用的中的对象的。其存在就是为了监听关联的虚引用被GC之后,收到系统的通知。

弱引用的对象需要借助java.lang.ref.PhantomReference,实现对象的弱引用。

// 引用队列
ReferenceQueue<Object> rq = new ReferenceQueue<>();
// 弱引用
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), rq);
System.out.println(DateUtil.now() + " 虚引用方法已执行!");

// 3s后GC
new Timer().schedule(new TimerTask() {
    @Override
    public void run() {
        System.gc();
    }
}, 3000);

// 监控回收事件的新线程
new Thread(() -> {
    try {
        rq.remove(); // 阻塞直到对象被回收
        System.out.println(DateUtil.now() + " 对象已被GC回收!");
    } catch (Exception e) {
        e.printStackTrace();
    }
}).start();

// 阻塞主线程
System.in.read();

执行结果

可以看到,调用GC之后,虚引用也会被直接回收,同时可以唤醒ReferenceQueue.remove()方法,通知被GC

小结一下:

  • 特点
    • 无法通过get()获取对象(永远返回null)
    • 必须配合ReferenceQueue使用
    • 对象回收时收到系统通知
  • 场景
    • 精准监控大对象回收(如1GB的缓存被回收时触发重建)
    • 资源清理(如JDK的Cleaner机制替代finalize())

04 四大引用对比总结

引用类型回收时机是否阻塞OOM常见场景
强引用永不回收❌ 可能引发普通对象持有
软引用内存不足时✅ 避免缓存
弱引用下次GC时✅ 避免防内存泄漏
虚引用GC后收到通知✅ 避免对象回收监听

05 小结

在日常开发中最常见的还是强引用,而其他引用用的比较少。其他引用主要用在架构的设计或者工具的设计上。合理的使用四大引用,可以让你的代码能力更上一层楼。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

智_永无止境

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

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

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

打赏作者

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

抵扣说明:

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

余额充值