Java中的软引用-Java快速入门教程
1. 概述
在这篇快速文章中,我们将讨论 Java 中的软引用。
我们将解释它们是什么,为什么我们需要它们,以及如何创建它们。
2. 什么是软引用?
软引用对象(或软可访问的对象)可以由垃圾回收器清除,以响应内存需求。软可访问的对象没有指向它的强引用。
当垃圾回收器被调用时,它开始循环访问堆中的所有元素。GC 将引用类型对象存储在特殊队列中。
检查堆中的所有对象后,GC 通过从上述队列中删除对象来确定应删除哪些实例。
这些规则因 JVM 实现而异,但文档指出,在 JVM 抛出 OutOfMemoryError 之前,保证清除所有对软可访问对象的软引用。
但是,不保证清除软引用的时间或清除一组此类引用对不同对象的顺序。
通常,JVM 实现在清理最近创建的引用或最近使用的引用之间进行选择。
软可触及的对象在最后一次引用后将保持活动状态一段时间。默认值是堆中每可用兆字节生存期一秒。可以使用 -XX:SoftRefLRUPolicyMSPerMB 标志调整此值。
例如,要将值更改为 2.5 秒(2500 毫秒),我们可以使用:
-XX:SoftRefLRUPolicyMSPerMB=2500
与弱引用相比,软引用可以具有更长的生存期,因为它们会继续存在,直到需要额外的内存。
因此,如果我们需要尽可能长时间地将对象保存在内存中,它们是更好的选择。
3. 软引用用例
软引用可用于实现内存敏感型缓存,其中内存管理是一个非常重要的因素。
只要软引用的引用是强可访问的,即 – 实际使用中,就不会清除引用。
例如,缓存可以通过保留对这些条目的强引用来防止丢弃其最近使用的条目,而剩余的条目则由垃圾回收器自行决定丢弃。
4. 使用软引用
在Java中,软引用由java.lang.ref.SoftReference类表示。
我们有两个选项来初始化它。
第一种方法是仅传递引用对象:
StringBuilder builder = new StringBuilder();
SoftReference<StringBuilder> reference1 = new SoftReference<>(builder);
第二个选项意味着传递对java.lang.ref.ReferenceQueue的引用以及对引用的引用。引用队列旨在让我们了解垃圾回收器执行的操作。当它决定删除此引用的引用对象时,它会将引用对象追加到引用队列。
以下是使用 ReferenceQueue 初始化 SoftReference 的方法:
ReferenceQueue<StringBuilder> referenceQueue = new ReferenceQueue<>();
SoftReference<StringBuilder> reference2
= new SoftReference<>(builder, referenceQueue);
作为java.lang.ref.Reference,它包含分别获取和重置引用的获取和清除方法:
StringBuilder builder1 = reference2.get();
reference2.clear();
StringBuilder builder2 = reference2.get(); // null
每次我们使用这种引用时,我们都需要确保存在由 get 返回的引用:
StringBuilder builder3 = reference2.get();
if (builder3 != null) {
// GC hasn't removed the instance yet
} else {
// GC has cleared the instance
}