强引用不被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免费学习笔记(深入)”;
BJXSHOP购物管理系统是一个功能完善、展示信息丰富的电子商店销售平台;针对企业与个人的网上销售系统;开放式远程商店管理;完善的订单管理、销售统计、结算系统;强力搜索引擎支持;提供网上多种在线支付方式解决方案;强大的技术应用能力和网络安全系统 BJXSHOP网上购物系统 - 书店版,它具备其他通用购物系统不同的功能,有针对图书销售而进行开发的一个电子商店销售平台,如图书ISBN,图书目录
- 构造方式:
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 对软引用的处理就不完全一致。









