1 简述
虚引用是使用PhantomReference创建的引用,虚引用也称为幽灵引用或者幻影引用,是所有引用类型中最弱的一个。如果一个对象与GC Roots之间仅存在虚引用,
则称这个对象为虚可达(phantom reachable)对象,一个对象是否有虚引用的存在,
完全不会对其生命周期构成影响,也无法通过虚引用获得一个对象实例。
2 使用
2.1 创建弱引用
//创建一个强引用变量s,将对象地址设置给变量s这个引用
String s = new String("Frank");
//创建一个Reference对象phantomRef,将对象地址设置给phantomRef.reference引用
PhantomReference phantomRef = new PhantomReference<String>(s);
//强引用不在指向new String("Frank"),此时new String("Frank")为弱可达对象
s = null;
这里new PhantomReference()本身也是堆中对象。指向对象地址的是其内部属性变量reference,在这里我把他称为引用,由于是PhantomReference创建引用所以我们把它称为虚引用
imagereferenceQueue队列
ReferenceQueue<T> referenceQueue = new ReferenceQueue<>();
//创建一个Reference对象phantomRef2,将对象地址设置给phantomRef2.reference引用
//同时给softRef2设置referenceQueue
PhantomReference<Object> phantomRef2 = new PhantomReference<>(new Object(),referenceQueue);
当引用对象new Object()将被回收时,会将reference对象放置进referenceQueue队列中。通过监控这个队列,取出reference对象,就可以对reference对象(存在堆中被phantomRef2引用)进行清理工作。
image2.2 释放弱引用
phantomRef2.clear();
3 WeakReference 源码
WeakReference源码可以说非常少,其功能基本继承至父类Reference
public class PhantomReference<T> extends Reference<T> {
public T get() {
return null;
}
public PhantomReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
}
}
案例
虚引用基本时用来和ReferenceQueue联合使用监听某个对象的回收时机
/**
* -verbose:gc -Xms4m -Xmx4m -Xmn2m
* 虚引用基本时用来和ReferenceQueue联合使用监听某个对象的回收时机
*/
public class PhantomReferenceTest {
private static final List<Object> TEST_DATA = new LinkedList<>();
private static final ReferenceQueue<TestClass> QUEUE = new ReferenceQueue<>();
public static void main(String[] args) {
/** 监听new TestClass("Test")对象回收时机 **/
PhantomReference<TestClass> phantomReference = new PhantomReference<>(new TestClass("Test"), QUEUE);
// 该线程不断读取这个虚引用,并不断往列表里插入数据,以促使系统早点进行GC
new Thread(() -> {
while (true) {
TEST_DATA.add(new byte[1024 * 100]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
System.out.println(phantomReference.get());
}
}).start();
// 这个线程不断读取引用队列,当弱引用指向的对象呗回收时,该引用就会被加入到引用队列中
new Thread(() -> {
while (true) {
Reference<? extends TestClass> poll = QUEUE.poll();
if (poll != null) {
System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
System.out.println("--- 回收对象 ---- " + poll.get());
}
}
}).start();
try {
Thread.currentThread().join();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
}
}
static class TestClass {
private String name;
public TestClass(String name) {
this.name = name;
}
@Override
public String toString() {
return "TestClass - " + name;
}
}
}
网友评论