强引用不被GC回收,内存溢出也不释放;软引用在内存不足时回收,适合内存敏感缓存;弱引用在下次GC即回收,用于避免泄漏;虚引用仅监听回收时机,需配合ReferenceQueue使用。

强引用不会被GC回收,哪怕内存溢出也不放人
Java里最常用的就是强引用,比如 Object obj = new Object()。只要这个变量还在作用域里、没被赋值为 null,JVM 就认定它“必须活着”,哪怕堆内存快爆了,GC 也不会动它——宁可抛 OutOfMemoryError 也不会回收。
常见错误现象:缓存用 HashMap 存大量对象,key 是强引用,即使业务上已不再需要,GC 也收不走,最终 OOM。
- 适用场景:绝大多数日常对象,比如 DTO、Service 实例、配置类
- 注意别在长生命周期容器(如静态 Map)里无意识持强引用,尤其持有 Activity、Context(Android)或 ServletRequest(Web)这类易泄露对象
- 若需“可回收缓存”,得换软引用或弱引用,不能硬扛
软引用适合做内存敏感型缓存
SoftReference 的特点是:JVM 在内存不足时才回收它,且会尽量保留最近访问过的软引用对象。它比强引用“松”一点,但比弱引用“紧”一点。
使用场景典型是图片缓存、模板缓存、解析结果缓存——你希望它们常驻内存提升性能,但又不想因缓存导致 OOM。
立即学习“Java免费学习笔记(深入)”;
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 构造方式:
new SoftReference(obj),取值前必须判空:if (ref.get() != null) { ... } - JDK 8+ 中,
SoftReference的回收策略由 JVM 参数-XX:SoftRefLRUPolicyMSPerMB控制,默认每 MB 堆空间保留软引用 1000ms,不是严格 LRU - 别把它当“自动清理缓存”用:如果堆够大,软引用可能长期不回收;如果堆小,刚放进缓存就没了——得配合大小限制或时间淘汰逻辑
弱引用只活到下一次 GC,适合临时绑定与避免内存泄漏
WeakReference 的生命周期极短:只要发生 GC(哪怕是 Young GC),它包裹的对象就会被回收。它的核心价值不是缓存,而是“关联但不阻止回收”。
典型错误现象:自定义监听器注册后没反注册,监听器内部持有了 Activity 强引用,导致 Activity 无法释放——用 WeakReference 包一层监听器实例就能破局。
- 常用搭配:
WeakHashMap的 key 是弱引用,value 不影响 key 的存活;适合做元数据映射(如代理类 → 原始类信息) - 不要指望靠它做缓存:哪怕刚 put 进去,下一次 GC 就可能 get 到
null - 注意并发问题:
get()返回null后,多个线程可能同时重建对象,需配合ConcurrentHashMap.computeIfAbsent等原子操作
虚引用几乎不持有对象,只用来监听回收时机
PhantomReference 是最特殊的一个:它的 get() 永远返回 null,你根本拿不到对象本身。它唯一作用是——当对象被 GC 回收时,JVM 会把该虚引用加入关联的 ReferenceQueue,让你能感知“它刚刚没了”。
别用它做资源清理主逻辑:finalize 已废弃,而虚引用没有执行时机保证,GC 可能卡住、延迟入队,甚至永远不入队(如果 ReferenceHandler 线程阻塞)。
- 正确姿势:配合
ReferenceQueue使用,仅用于记录日志、触发异步清理(比如关闭文件句柄、释放 off-heap 内存) - 必须显式调用
cleanUp()类方法完成资源释放,不能依赖“入队即清理” - 容易踩坑:忘记传
ReferenceQueue构造虚引用,那就彻底失去监听能力;或者误以为PhantomReference能替代try-with-resources,其实它连 close 都不负责
四种引用的本质差异不在“强度”,而在 GC 时 JVM 对它们的处理策略和时机。最容易被忽略的是:虚引用必须配合队列使用才有意义,而软/弱引用的回收行为高度依赖 JVM 版本和 GC 算法——OpenJDK 17 的 ZGC 和 G1 对软引用的处理就不完全一致。

















