Java 软引用详解
大约 2 分钟JavaJuc
软引用
使用软引用和弱引用的原因是防止内存溢出,因为内存不够时就可以回收软引用或弱引用所指向的内容
MyObject aRef = new MyObject();
SoftReference aSoftRef = new SoftReference(aRef);
MyObject anotherRef = (MyObject)aSoftRef.get();这段代码的引用关系是:
[变量 aSoftRef] --(强引用)--> [SoftReference 实例] --(软引用)--> [MyObject 实例]当软引用所指向的对象只有软引用并且堆内存空间不足时,会把软引用所指向的对象进行回收,但是并不会把软引用实例本身进行回收。
为什么不回收软引用实例本身?
设计原因
需要维护访问桥梁
- 软引用对象是程序与目标对象之间的"桥梁"
- 如果软引用对象被回收,程序就无法查询目标对象的状态
提供查询机制
MyObject obj = (MyObject)aSoftRef.get(); // 通过 get() 方法可以: // - 获取目标对象(如果还存在) // - 返回 null(表示目标对象已被回收)支持引用队列通知
ReferenceQueue<MyObject> queue = new ReferenceQueue<>(); SoftReference<MyObject> softRef = new SoftReference<>(obj, queue); // 当目标对象被回收后,softRef 会被加入队列 // 程序可以通过队列得知哪些对象被回收,进行清理工作便于缓存管理
Map<String, SoftReference<BigData>> cache = new HashMap<>(); // 需要保留软引用对象,才能管理和清理Map中的条目
内存管理责任划分
| 对象类型 | 管理方式 | 说明 |
|---|---|---|
| 目标对象 (MyObject) | ✅ JVM 自动管理 | 内存不足时自动回收,程序员无需干预 |
| 软引用对象 (SoftReference) | 🔄 普通对象规则 | 有强引用就保留,无强引用就会被GC |
| 数据结构清理 | ⚠️ 程序员负责 | 需要清理Map等容器中的过期软引用 |
核心要点
- 目标对象的回收:完全由JVM根据内存情况自动决定
- 软引用对象本身:遵循普通对象的GC规则,由程序控制生命周期
- 程序员职责:主要是检查对象是否还在,并清理数据结构中的过期引用
设计优势
这种两层设计带来的好处:
- ✅ 自动内存压力感知(不需要程序员判断内存是否充足)
- ✅ 保留查询和通知能力
- ✅ 支持灵活的缓存管理策略
- ✅ 平衡了自动化和可控性