JAVA中的四种引用
对象的强、软、弱和虚引用
在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(reachable)状态,程序才能使用它。从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
强引用:
只要引用存在,垃圾回收器永远不会回收。
设计说明:
- 只要引用存在就不会被GC回收。
Object obj = new Object();
//可直接通过obj取得对应的对象 如obj.equels(new Object());
而这样 obj对象对后面new Object的一个强引用,只有当obj这个引用被释放之后,对象才会被释放掉,这也是我们经常所用到的编码形式。
软引用:
非必须引用,内存溢出之前进行回收,可以通过以下代码实现。
设计说明:
- 创建软引用,当软引用被引用之后,对象就变成了强引用。
- 强引用释放后,不会被立即销毁,又变成软引用。
- 在内存不够的时候,将这部分引用回收。
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
sf.get();//有时候会返回null
意义:
- 软引用主要用户实现类似缓存的功能,在内存足够的情况下直接通过软引用取值,无需从繁忙的真实来源查询数据,提升速度;
- 当内存不足时,自动删除这部分缓存数据,从真正的来源查询这些数据。
弱引用:
第二次垃圾回收时回收,可以通过如下代码实现。
设计说明:
- 创建弱引用,当软引用被引用之后,对象就变成了强引用。
- 强引用释放后,不会被立即销毁,又变成弱引用。
- 当经历第二次GC的时候,将这部分引用回收。
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
wf.get();//有时候会返回null
wf.isEnQueued();//返回是否被垃圾回收器标记为即将回收的垃圾
意义
- 弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。
- 弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
虚引用:
垃圾回收时回收,无法通过引用取到对象值,可以通过如下代码实现。
设计说明:
- 对象创建,关联虚引用;
- 对象不再被引用,进入GC,这个时候会被添加到虚引用队列;
- 死循环从虚引用队列中轮询出列,当出列对象不为空的时候,这个时候可在对象回收之前做处理。
- 从虚引用队列中出列后,对象下次GC时回收。
public class PhantomReferenceTest {
static ReferenceQueue<Object> queue = new ReferenceQueue<>();
static List<byte[]> aryList = new ArrayList<>();
public static void main(String[] args) {
Object obj = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj, queue);
if (queue.poll() == null) {
System.out.println("这个时候队列里面还是没有数据的");
}
System.out.println("查看虚引用获取对象的结果:"+phantomReference.get());
// 释放对象,好让GC的时候回收
obj = null;
int i = 0;
while (true) {
aryList.add(new byte[100 * 1024]);
if (queue.poll() != null) {
System.out.println("这个时候队列里面有数据了,说明触发了GC,我们可以在对象回收之前做相应的操作");
break;
} else {
System.out.println("创建了" + (++i * 100) + "K数据");
}
}
}
}
这个时候队列里面还是没有数据的
查看虚引用获取对象的结果:null创建了100K数据
创建了200K数据…
这个时候队列里面有数据了,说明触发了GC,我们可以在对象回收之前做相应的操作
意义
- 虚引用对于对象而言完全是无感知的,有没有完全一样,但是对于虚引用的使用者而言,就像是待观察的对象的把脉线,可以通过它来观察对象是否已经被回收,从而进行相应的处理。
- 使用虚引用的目的就是为了得知对象被GC的时机,所以可以利用虚引用来进行销毁前的一些操作,比如说资源释放等。