最近在翻JVM的资料,对于4种引用有不少疑问
Q1.强引用如何判断?
Q2.ReferenceQueue的作用?
Q3.4种引用分别的用途?
Q4.强引用一定不回收?
A1.
对于JDK提供的SoftReference/WeakReference/PhantomReference,我们可以简单的通过instanceof
来判断
但是并没有StrongReference,也没有显式判断的API(可能是我不会搜索..
目前想到的方法就是用排除的方法,你应该懂我意思
A2.
当Reference被回收时,与它关联的ReferenceQueue会把它入队,以便真正的回收(.get()不会报错,那意味着指向的对象被回收,但该Reference的存在依然是实例,而不是null)
(Q.为什么不直接if(ref.get()==null) ref = null?)
A3.
1.强引用:重要的对象
2.软引用:有用但不重要的对象,比如缓存,当你面临OOM时可以干掉而不影响正常工作
4.幽灵引用:用于分析GC
3.弱引用:我暂时不太理解用途。。。(由1/2推理得为没用又不重要的东西??orz)
A4.
已知有一种情况依然会回收,比如放在某个方法上,如果显示使用gc()的话还是会回收的
A5.
一个彩蛋是发现反射可能是隐式使用多线程,待考究
文章待看:
https://www.jianshu.com/p/f0da6c1af815
直接看代码
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.PriorityQueue;
import java.util.Scanner;
class Xjb {
String str;
public Xjb(String str) {
this.str = str;
}
public Xjb() {
this.str = null;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize! " + str);
}
@Override
public String toString() {
return str.toString();
}
}
public class Main {
public static void print(Object...objs) {
Xjb xjb = new Xjb("temp");
for(Object obj:objs) {
System.out.println(obj);
}
}
public static void main(String[] args) throws InterruptedException {
Xjb str = new Xjb("str");
Reference<Xjb> sr = new SoftReference<Xjb>(new Xjb("sr"));
Reference<Xjb> wr = new WeakReference<>(new Xjb("wr"));
Reference<Xjb> pr = new PhantomReference<Xjb>(new Xjb("pr"), new ReferenceQueue<>());
Class clazz = str.getClass();
wr = null; // 需要注释
System.out.println(wr instanceof WeakReference);
System.out.println(clazz != null
&& !clazz.isInstance(new SoftReference<>(new Xjb("tempSr")))
&& !clazz.isInstance(new WeakReference<>(new Xjb("tempWr")))
&& !clazz.isInstance(new PhantomReference<Xjb>(new Xjb("tempPr"), new ReferenceQueue<>())));
// 疑似反射会隐式调用多线程,有一定概率没来得及输出就抛出异常
print(str,sr.get(),wr.get(),pr.get());
System.out.println("GC + SLEEP...");
System.gc();
Thread.currentThread().sleep(2333L);
print(str,sr.get(),wr.get(),pr.get());
}
}