引用类型决定对象存活时间:强引用永不回收;软引用在内存不足时回收;弱引用每次gc都可能回收;虚引用不阻止回收,仅用于回收通知。

引用类型直接决定对象在堆内存中能“活多久”。不是所有对象都等 GC 来统一清理,JVM 会根据引用强度,在不同内存压力和回收阶段做出差异化处理。关键不在于“能不能被回收”,而在于“什么时候、什么条件下被回收”。
强引用:只要它还连着,就绝不放手
这是最硬的绑定。只要栈帧里还存着变量(比如 Object obj = new Object()),或者对象被其他强引用链可达,GC 就不会碰它——哪怕内存已经爆了,JVM 宁愿抛 OutOfMemoryError 也不会动它。
- 方法内创建的局部对象,在方法执行完前始终存活
- 成员变量引用的对象,只要宿主对象没被回收,它就安全
- 想提前释放?只能显式赋值为
null,切断强引用链
软引用:内存紧张时的“优先牺牲者”
软引用对象是“可有可无但最好留着”的存在。JVM 会在每次 GC 后检查堆内存是否仍不足;只有确认内存确实不够用时,才会批量回收所有软引用指向的对象。
- 回收时机不是“内存快满”,而是“GC 后仍 OOM 风险高”
- 适合做缓存:比如图片加载库(Glide)用它缓存解码后的 Bitmap
-
SoftReference.get()返回 null,说明已被回收,需重新加载
弱引用:下一次 GC 就可能消失
比软引用更“脆弱”。只要发生 GC(无论内存是否充足),弱引用对象就会被立即回收。它不参与内存压力判断,只表达“我存在,但不值得保留”。
- 典型用途:避免内存泄漏的监听器、缓存映射表(如
WeakHashMap) - ThreadLocal 的 value 若未手动 remove,就靠弱引用来防止线程长期持有对象
- 不能依赖它的长期存在,每次使用前必须判空
虚引用:唯一不决定存活时间的引用
虚引用(PhantomReference)本身不阻止对象被回收,它的 get() 永远返回 null。它存在的唯一意义,是让程序能在对象被真正清除前收到通知。
- 必须配合引用队列(
ReferenceQueue)使用 - 常用于资源清理:比如对象关联了文件句柄或 socket,可在虚引用入队后做 finalize 式收尾
- 它不延长对象寿命,也不影响 GC 决策,纯粹是回收事件的“哨兵”











