Java四种引用类型按强度递减为强、软、弱、虚引用:强引用使对象永不回收;软引用在OOM前被回收,用于缓存;弱引用在每次GC时立即回收,用于WeakHashMap;虚引用仅作回收通知,需配合ReferenceQueue使用。

Java中四种引用类型直接影响对象在堆内存中的存活时间与回收时机,不是“有没有引用”,而是“引用有多强”决定了GC是否清理它。
强引用:堆内存的“硬钉子”
只要强引用链存在(比如局部变量、静态字段、活动线程栈帧中的引用),对象就始终驻留在堆中,哪怕内存即将耗尽,JVM也宁抛OutOfMemoryError也不回收。这导致堆内存持续占用,是内存泄漏的主因——例如静态Map长期持有Activity实例,Activity无法释放,其整个视图树和资源全卡在堆里。
- 必须显式断开(如赋值null)或等作用域自然结束,GC才可能将其标记为可回收
- 不配合任何ReferenceQueue,GC对其完全“无视”
- 适合生命周期明确、必须稳定存在的对象,如单例、配置类、核心业务实体
软引用:堆内存的“弹性缓冲区”
软引用对象保留在堆中,直到JVM判断内存即将OOM(通常在Full GC前触发二次判定)。此时GC会批量清理所有软引用指向的对象,腾出空间避免崩溃。因此它让堆内存使用具备自适应性——空闲时缓存常驻,紧张时自动收缩。
- 回收时机不可控,取决于当前堆压力和GC策略(如G1的IHOP阈值)
- 使用前必须判空:if (softRef.get() != null),否则易发NPE
- 适合图片、报表、解析结果等“有用但可重建”的缓存数据
弱引用:堆内存的“瞬时快照”
只要发生任意一次GC(Young GC或Full GC),仅被弱引用持有的对象就会立即从堆中清除。它不缓冲、不等待,使堆内存能快速响应引用关系变化,防止无用对象滞留。
立即学习“Java免费学习笔记(深入)”;
- WeakHashMap的key即用弱引用实现:key被回收后,对应Entry在下次访问时自动清理(但value需手动处理,否则仍占堆)
- ThreadLocal的key也是弱引用——避免线程长期运行导致Entry堆积,但value若未及时remove,仍会造成内存泄漏
- 访问时同样要判空,且不能依赖其长期存在
虚引用:堆内存的“回收哨兵”
虚引用本身对堆内存零影响——它既不能获取对象(get()恒返回null),也不延缓回收。它的唯一作用是在对象被GC真正清除前,将虚引用推入关联的ReferenceQueue,通知程序执行清理动作(如释放DirectByteBuffer的堆外内存)。
- 对象进入Finalizer队列或直接回收时,虚引用才会入队,因此必须轮询队列才能感知回收事件
- 必须搭配ReferenceQueue使用,单独创建无意义
- 典型场景是资源型对象的确定性清理,避免堆外内存泄漏或文件句柄耗尽


















