1. 概述
本文将快速介绍Java中的软引用(Soft References)。我们会解释它的概念、使用场景以及如何创建和使用它。
2. 什么是软引用?
软引用对象(或称为软可达对象)在内存不足时会被垃圾回收器清除。核心特征是:软可达对象没有任何强引用指向它。
当垃圾回收器(GC)工作时,会遍历堆内存中的所有对象。GC会将引用类型的对象放入一个特殊队列中。完成堆内存检查后,GC通过清理该队列中的对象来决定哪些实例需要被回收。
不同JVM实现的具体规则可能不同,但文档明确说明:所有指向软可达对象的软引用,在JVM抛出OutOfMemoryError之前一定会被清除。
⚠️ 需要注意:
- 软引用被清除的时间点没有保证
- 多个软引用的清除顺序也没有保证
通常,JVM实现会在清理最近创建的引用和最近使用的引用之间做选择。软可达对象在最后一次被引用后仍会存活一段时间,默认值是堆中每空闲1兆字节存活1秒。这个值可以通过 -XX:SoftRefLRUPolicyMSPerMB
参数调整,例如:
-XX:SoftRefLRUPolicyMSPerMB=2500
与弱引用相比,软引用的生命周期更长,因为它们会持续存在直到内存真的不够用。因此,当我们需要尽可能长时间地在内存中保留对象时,软引用是更好的选择。
3. 软引用的使用场景
软引用特别适合实现内存敏感的缓存,在这种场景下内存管理至关重要。
只要软引用的引用对象是强可达的(即正在被使用),该引用就不会被清除。例如,缓存可以这样设计:
- 对最近使用的条目保持强引用
- 让其他条目由垃圾回收器根据内存状况决定是否丢弃
✅ 典型应用场景:
- 图片缓存
- 大对象临时存储
- 计算结果缓存
4. 使用软引用
在Java中,软引用通过 java.lang.ref.SoftReference
类表示。有两种初始化方式:
方式1:仅传入引用对象
StringBuilder builder = new StringBuilder();
SoftReference<StringBuilder> reference1 = new SoftReference<>(builder);
方式2:同时传入引用对象和引用队列
ReferenceQueue<StringBuilder> referenceQueue = new ReferenceQueue<>();
SoftReference<StringBuilder> reference2
= new SoftReference<>(builder, referenceQueue);
引用队列(ReferenceQueue)的作用:当垃圾回收器决定清除某个引用对象时,会将该引用对象加入引用队列,这样我们就能感知GC的操作。
作为 java.lang.ref.Reference
的子类,SoftReference
提供了两个核心方法:
get()
:获取引用对象clear()
:清除引用对象
StringBuilder builder1 = reference2.get();
reference2.clear();
StringBuilder builder2 = reference2.get(); // 返回null
每次操作软引用时,必须检查引用对象是否还存在:
StringBuilder builder3 = reference2.get();
if (builder3 != null) {
// GC还没回收这个实例
} else {
// GC已经清除了实例
}
5. 总结
本文介绍了软引用的核心概念和使用场景,并展示了如何创建和操作软引用。合理使用软引用可以在内存管理和对象缓存之间取得平衡,但需要注意其生命周期的不确定性。