当然啦,大神们肯定知道各种引用的差别.在这里列出来主要是为了下面的例子.
强引用,垃圾回收的时候无论如何都不会被回收的
软引用,垃圾回收的时候发现内存依然不够存储新的对象的情况下就会被回收
弱引用,垃圾回收的时候无论如何都会被回收的
虚引用,垃圾回收的时候收到一个通知
可达性分析法从GCROOT顺着引用链无法访问到的对象.通常GCROOT有以下几种:
虚拟机栈中的变量
本地方法栈中的变量
类的静态变量
类中的常量
public class RefTest {
public static class Galis {
String name = "Hello";
}
public static class GalisThread extends Thread {
Galis galis;
GalisThread() {
galis = new Galis();
}
}
public static void main(String[] args) throws InterruptedException {
GalisThread refThread = new GalisThread();
galisThread.start();
galisThread.join();
Galis refGalis = refThread.galis;
// SoftReference refGalis = new SoftReference(galisThread.galis);
// WeakReference refGalis = new WeakReference(galisThread.galis);
System.gc();
System.out.println(refGalis.toString());
}
}
首先我们清楚refGalis引用的是refThread对象中的实体galis.
当实体galis不被回收的时候,refGalis.toString()永远不会出现问题.
我们可以画出galis的引用链.
VM代表线程在运行的时候,虚拟机内部某处有线程控制块指向当前线程.当然这里线程已经运行结束了,所以就为红色.
以上情况,无论refGalis为何种引用,总有refThread->线程实体->内部galis实体,所以refGalis.toString()永远不会出现问题.
public static void main(String[] args) throws InterruptedException {
GalisThread refThread = new GalisThread();
galisThread.start();
galisThread.join();
Galis refGalis = galisThread.galis;
// SoftReference refGalis = new SoftReference(galisThread.galis);
// WeakReference refGalis = new WeakReference(galisThread.galis);
refThread=null;
System.gc();
System.out.println(refGalis.toString());
}
上面图可以知道,只有一个GCROOT可以到达内部galis实体,所以这个时候refGalis是何种引用就很关键了.
强引用的时候,GC后,galis实体不会被回收,refGalis.toString()不会报错.
软引用的时候,GC后,因为内存够用,galis实体不会被回收,refGalis.toString()不会报错.
弱引用的时候,GC后,galis实体肯定会被回收,refGalis.toString()会报空指针.
因此我们可以知道要想回收某个实体,必须没有GCROOTS可以引用到它或者是该引用是软引用,弱引用
.