在 JDK 1.2 版本之前,Java中的引用是很传统的定义:如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,就称该reference数据是代表某块内存、某个对象的引用。这种定义并没有什么不对,知识现在看来有些过于狭隘了,一个对象在这种定义下只有“被引用”或者“未被引用”两种状态,对于描述一些“食之无味,弃之可惜”的对象就显得无能为力。譬如我们希望能描述一类对象:当内存空间还足够时,能保留在内存中,如果内存空间在进行垃圾收集后仍然非常紧张,那就可以抛弃这些对象----很多系统的缓存功能都符合这样的应用场景。
在JDK 1.2 版之后,Java对引用的概念进行了扩充,将引用分为强引用(Strongly Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱。
强引用 - StrongReference
在 Java 中强引用是一种最常见的对象引用,把对象赋值给一个引用变量,那么这个变量就是一个强引用。例如使用关键字 new 创建的对象就是强引用,强引用是绝对不会被垃圾收集器回收的,当 JVM 内存空间不足时,JVM 即使抛出 OutOfMemoryError 错误也不会对强引用进行垃圾回收释放内存空间的。
String str = "abc";
软引用 - SoftReference
软引用是用来描述一些还有用,但非必须得对象,只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK1.2版之后提供了SoftReference类来实现软引用。
例如Springboot 中加载文件时的缓存:
SoftReference<Object> softRef = new SoftReference<>(obj);
弱引用 - WeakReference
弱引用也是用来描述哪些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2版之后提供了WeakReference类来实现弱引用。
例如:java.util.WeakHashMap
WeakReference<Object> weakRef = new WeakReference<>(obj)
虚引用 - PhantomReference
虚引用也称为“幽灵引用”或者“幻影引用”,她是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象的实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK1.2版之后提供了PhantomReference类来实现虚引用。
虚引用的主要作用是跟踪对象被垃圾回收的状态。
PhantomReference<Object> phantomRef = new PhantomReference<>(obj, referenceQueue);
引用强度
强引用 > 软引用 > 弱引用 > 虚引用
扩展
使用软引用实现JVM高速缓存
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
public class SoftReferenceCache<K, V> {
private final Map<K, SoftReference<V>> cache = new HashMap<>();
public void put(K key, V value) {
SoftReference<V> softReference = new SoftReference<>(value);
cache.put(key, softReference);
}
public V get(K key) {
SoftReference<V> softReference = cache.get(key);
if (softReference != null) {
return softReference.get();
} else {
return null;
}
}
public void clear() {
cache.clear();
}
}

被折叠的 条评论
为什么被折叠?



