Java对象生命周期由强、软、弱、虚四种引用类型分级控制:强引用禁止GC回收,软引用在内存不足时回收,弱引用每次GC必回收,虚引用不阻止回收但可感知回收时机。

Java中对象的生命周期不只由代码作用域决定,更由引用类型直接控制。强、软、弱、虚四种引用构成了一套渐进式回收策略——强度逐级降低,GC介入时机逐级提前。理解它们,等于掌握了内存管理的主动权。
强引用:默认且最“固执”的存在
Object obj = new Object() 这样的写法就是强引用。只要这个变量还持有对象,JVM宁可抛出OutOfMemoryError也绝不回收它。这不是“保守”,而是设计使然:业务核心对象必须稳定可达。
- 显式断开是释放前提:obj = null 是常见做法,但更关键的是让引用自然超出作用域(比如方法结束)
- 静态集合容易埋雷:static List<Object> cache = new ArrayList<>() 中添加的对象,即使局部变量置null,仍因静态引用无法回收
- 不是所有强引用都要手动置null:现代JVM对局部变量有逃逸分析,很多场景下无需干预
软引用:内存压力下的“缓存守门人”
SoftReference<byte[]> ref = new SoftReference<>(new byte[10 * 1024 * 1024])。它不保证常驻,但也不轻易离场——仅在JVM判定“再不清理就要OOM”时才被回收,且总在抛异常前完成。
- 适合做图片、HTML片段等体积大、重建成本高但非强一致性的缓存
- 配合ReferenceQueue可监听回收事件,用于清理关联资源(如关闭文件句柄)
- 注意:get()返回可能为null,每次使用前必须判空,不能假设它一定还活着
弱引用:GC一扫就“消失”的临时凭证
WeakReference<String> wref = new WeakReference<>(new String("hello"))。它的特点是“下次GC必收”,不管堆内存是否充足。这种“朝生暮死”的特性,让它天然适配短期映射场景。
立即学习“Java免费学习笔记(深入)”;
- WeakHashMap的key就是弱引用:当key对象无其他强引用时,整条Entry自动失效,避免内存泄漏
- ThreadLocal内部用WeakReference作key:防止线程长期运行导致value无法释放
- 不适合做常规缓存:存活时间不可控,命中率低,频繁重建反而增加GC压力
虚引用:唯一不参与“保命”的引用
PhantomReference<Object> pref = new PhantomReference<>(obj, queue)。它不能通过get()获取对象(永远返回null),存在的唯一意义是——当对象被回收时,JVM会把该虚引用加入关联的ReferenceQueue,通知你“它走了”。
- 典型用途是资源清理:比如NIO的DirectByteBuffer,用虚引用配合Cleaner做堆外内存回收通知
- 必须搭配ReferenceQueue使用,单独创建虚引用毫无意义
- 不是“延后回收”,而是“回收后通知”;对象进入F-Queue后,才会被真正清除


















