功能概述
- 从JDK1.2版本开始,程序可以通过4种类型的对象的引用来管控对象的生命周期。这4种引用分别为,强引用、软引用、弱引用和虚引用。本文中针对各种引用做了相关测试,并做对应分析。
功能实践
场景1:弱引用、虚引用、软引用基本使用
用例代码
@Test
public void test_reference_v1() {
ReferenceQueue<Ref> queue = new ReferenceQueue<>();
WeakReference<Ref> weak = new WeakReference<>(new Ref("Weak"), queue);
PhantomReference<Ref> phantom = new PhantomReference<>(new Ref("Phantom"), queue);
SoftReference<Ref> soft = new SoftReference<>(new Ref("Soft"), queue);
System.out.println("引用内容:");
System.out.println(weak.get());
System.out.println(phantom.get());
System.out.println(soft.get());
System.out.println("被回收的引用:");
for (Reference r = null; (r = queue.poll()) != null;) {
System.out.println(r);
}
}
class Ref {
Object v;
Ref(Object v) {
this.v = v;
}
public String toString() {
return this.v.toString();
}
}
运行结果
引用内容:
Weak
null
Soft
被回收的引用:
结果分析
- 弱引用对象和软引用对象都是可达的,但是虚引用对象不可点,phantom.get()调用时总是为null
- 创建弱引用、软引用、虚引用时,需要执行引用的的对象、引用对象注册的队列,如:new WeakReference<>(new Ref(“Weak”), queue)
场景2:GC垃圾回收时,对象引用的行为
用例代码
@Test
public void test_reference_v2() {
ReferenceQueue<Ref> queue = new ReferenceQueue<>();
WeakReference<Ref> weak = new WeakReference<>(new Ref("WeakV2"), queue);
PhantomReference<Ref> phantom = new PhantomReference<>(new Ref("PhantomV2"), queue);
SoftReference<Ref> soft = new SoftReference<>(new Ref("SoftV2"), queue);
System.out.println("引用内容V2:");
System.out.println(weak.get());
System.out.println(phantom.get());
System.out.println(soft.get());
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("被回收的引用V2:");
for (Reference r = null; (r = queue.poll()) != null; ) {
System.out.println(r);
}
运行结果
引用内容V2:
WeakV2
null
SoftV2
被回收的引用V2:
java.lang.ref.WeakReference@1b701da1
java.lang.ref.PhantomReference@726f3b58
结果分析
- 弱引用和虚引用都会回收了,软引用要在接近OOM异常时回收
场景3:GC垃圾回收时,关联强引用
用例代码
@Test
public void test_reference_v3() {
ReferenceQueue<Ref> queue = new ReferenceQueue<>();
Ref wr = new Ref("Hard");
WeakReference<Ref> weak = new WeakReference<>(wr, queue);
PhantomReference<Ref> phantom = new PhantomReference<>(wr, queue);
SoftReference<Ref> soft = new SoftReference<>(new Ref("Soft"), queue);
System.out.println("引用内容V3:");
System.out.println(weak.get());
System.out.println(phantom.get());
System.out.println(soft.get());
System.gc();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("被回收的引用V3:");
for (Reference r = null; (r = queue.poll()) != null; ) {
System.out.println(r);
}
}
运行结果
引用内容V3:
Hard
null
Soft
被回收的引用V3:
结果分析
- 弱引用、虚引用在创建时,若关联了强引用,在强引用可达时不会被回收
- 在强引用置为null,如wr=null,表明强引用可被回收,此时关联的弱引用、虚引用都可被回收
功能总结
- 多个引用说明:
- a)HardReference:强引用(注:没有这个类,只是形象说明),类似String str = new String()建立起来的引用,都是强引用。在str指向另一个对象或null之前都不会被GC回收(指向另一个对象,或str=null才会被GC回收)
- b)WeakReference:弱引用,当GC要求回收对象时,不会阻止对象被回收,即使有弱引用存在
- c)SoftReference:软引用,当GC要求回收对象时,也不会阻止对象被回收,但回收过程会有延迟,必须要等到JVM heap内存不够用,接近产生OutOfMemory错误时,才会被回收
- d)PhantomReference:虚引用,这种类型的引用比较特别,在大多数时间里,无法通过它拿到其引用的对象(即phantom.get()总是为null),但是,在这个对象消失的时候,该引用还是会进入ReferenceQueue队列中的