java中强、软、弱、虚四种引用决定对象gc存活资格:强引用永不回收;软引用在oom前回收;弱引用每次gc即回收;虚引用不阻止回收,仅用于对象死亡通知。

Java 中的强、软、弱三种引用,直接决定了对象在垃圾回收(GC)过程中的“存活资格”。它们不是语法糖,而是 JVM 垃圾回收策略的显式接口——同一块堆内存里的对象,因引用类型不同,GC 的处置逻辑截然不同。
强引用:GC 绝对绕道走
只要栈帧里还存着变量(比如 Object obj = new Object()),或者该对象被其他强引用链持续可达,GC 就不会碰它。哪怕老年代快满了、Minor GC 频繁触发、甚至已经抛出 OutOfMemoryError,JVM 也绝不会因为内存压力而去回收强引用对象。
- 这是默认引用方式,也是业务代码中最常见的写法
- 风险在于:若忘记置
null或存在循环引用(如 Activity 持有 Handler,Handler 又持有 Activity),对象会长期驻留,引发内存泄漏 - ArrayList 的
clear()方法会把数组元素逐个设为null,正是为了切断强引用链,协助 GC 回收
软引用:内存告急时才动手
用 SoftReference<t></t> 包裹对象,比如缓存一张大图:new SoftReference(loadBigImage())。它的特点是“能留则留”,GC 不会主动清理;只有在真正要 OOM 前的最后一次回收尝试中,才会批量回收所有软引用对象。
- 适合图片、JSON 解析结果等高构建成本、可重建、有缓存价值的数据
- 不能假设它一定撑到 OOM 前一刻——G1 和 ZGC 对软引用的回收阈值略有差异,有的更激进,有的更保守
- 建议配合
ReferenceQueue使用,一旦get()返回null,说明已被回收,可触发重新加载逻辑
弱引用:GC 跑一次就清掉
用 WeakReference<t></t> 包裹,比如 new WeakReference(new String("temp"))。只要发生任意一次 GC(哪怕是 Young GC),且该对象只被弱引用持有,就会立刻被回收。
- 不看内存是否充足,只看“有没有别的活引用”——这是它和软引用最本质的区别
- 典型场景:
WeakHashMap的 key 是弱引用,避免 key 持久驻留导致 Map 无限膨胀 -
ThreadLocal内部的Entry键使用弱引用,防止线程长期运行时 key 泄漏;使用前必须判空,get()返回null是常态
虚引用:不参与存活判定,只发“死亡通知”
用 PhantomReference<t></t> 包裹,必须关联 ReferenceQueue 才有意义。它不能通过 get() 获取原对象(永远返回 null),唯一作用是:当对象被 GC 清理后,JVM 把该虚引用加入队列,程序借此感知“对象已死”。
- 不阻止回收,也不影响 GC 决策,纯粹是生命周期监听钩子
- 常用于资源清理:比如释放堆外内存、关闭文件句柄、注销 native 资源——比已弃用的
finalize()更可靠、更可控 - 注意:虚引用对象在被回收前,必须确保其 finalize 阶段已完成(如果定义了),否则不会入队
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











