You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SoftReference自身何时被GC回收?GC如何处理引用对象已回收的SoftReference?

Java SoftReference 垃圾回收相关问题解答

首先先明确一个核心认知:SoftReference实例本身和它内部引用的目标对象(下称referent)是两个完全独立的堆对象,二者生命周期没有强制绑定关系,不要混为一谈。

SoftReference对象自身的GC回收时机

SoftReference本身没有任何回收特权,它的回收规则和普通Java对象完全一致:

  • 只要存在从GC Roots出发的强引用链能抵达这个SoftReference实例,它就绝对不会被回收,哪怕它内部持有的referent已经被GC清理、调用get()已经返回null。最常见的场景就是你把SoftReference实例作为value存到了缓存Map里,只要Map本身是存活的,这些SoftReference对象就会一直留在堆里。
  • 当不存在任何强/软/弱引用链指向这个SoftReference实例时,它会和其他普通不可达对象一样,在对应分代的GC触发时被正常回收,和它内部的referent是否存活没有关系。

常见误区:很多人以为referent被回收后SoftReference对象自己也会立刻被回收,这是完全错误的。举个最简单的例子:方法局部变量持有的SoftReference,哪怕内部referent因为内存不足被清掉了,只要方法没执行完、局部变量还没出作用域,这个SoftReference对象就一直是强可达的,不会被回收。

referent被回收后GC对SoftReference对象的处理

当GC判定某个SoftReference的referent达到软引用回收阈值(即下次GC后仍然没有足够内存分配、即将抛出OutOfMemoryError前,会回收所有软可达的referent),会对对应的SoftReference对象做如下处理:

  • 首先会原子性地把SoftReference内部存储referent的字段置为null,这之后调用get()方法就会返回null,和原referent对象的引用关联被彻底切断。
  • 后续处理取决于创建SoftReference时是否关联了ReferenceQueue:
    • 如果关联了注册的引用队列:JVM内置的ReferenceHandler后台线程会在GC完成后,把这个已经清空referent的SoftReference实例加入到对应的队列中。应用层可以轮询这个队列,拿到失效的SoftReference实例做后续清理,比如把它从自定义的缓存Map中移除,避免无效对象堆积。
    • 如果没有关联任何引用队列:GC做完referent置空的操作后就不会有额外处理,这个SoftReference对象会一直留在堆里,直到它自身不可达后被正常回收。

实践提示:如果用SoftReference做内存敏感缓存,一定要关联ReferenceQueue并及时清理队列里失效的SoftReference实例,否则大量持有null referent的SoftReference对象会被缓存Map强引用一直占用内存,造成意料之外的内存泄漏。

内容的提问来源于stack exchange,提问作者MD.Luffy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 08:25:30