可达性分析
该理论是jvm判断对象能否被回收的依据。静态属性引用的对象、常量引用的对象、本地变量表(方法的局部变量和实参)中引用的对象作为根,一步步找引用的对象。如果该对象能连到根,则认为是不可回收的;如果不能,则对象是可回收的。
图中的object1、2、3、4是不可回收的,object5、6、7是可回收的。注意:上面说的引用,指的是强引用。那什么是强引用呢?
Java里面的引用,由强到弱,依次的四种:强、软、弱、幽灵;下面详细描述。
强引用
我们在代码中最经常写的:Object o = new Object(); 从根到某对象的引用链一直都是强引用,那该对象不会被回收;如何去除强引用?o = null; 这样对象就去除强引用了。在垃圾回收器下次回收时,该对象会被认为是可回收的。
软引用
Object o = new Object();
SoftReference<Object> softReference = new SoftReference<>(o);
// 去除强引用,此时对象只有软引用
o = null;
// 打印对象
System.out.println(softReference.get());
软引用关联的对象,当内存空间不足时,该对象在下次回收时会被回收。
弱引用
Object o = new Object();
WeakReference<Object> weakReference = new WeakReference<>(o);
// 去除强引用,此时对象只有弱引用
o = null;
// 打印对象
System.out.println(weakReference.get());
弱引用关联的对象,无论内存空间是否充足,下一次回收时该对象会被回收。
幽灵引用
Object obj = new Object();
ReferenceQueue refQueue = new ReferenceQueue();
PhantomReference<Object> phantomReference = new PhantomReference<Objec
t>(obj, refQueue);
// 去除强引用,此时对象只有幽灵引用
obj = null;
// 打印对象,只会是null,获取不了
System.out.println(phantomReference.get());
幽灵引用关联的对象,和弱引用一样,无论内存空间是否充足,下一次回收时该对象会被回收。
下面给出一段代码:
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public class A {
private Object o;
private SoftReference<Object> softReference;
private WeakReference<Object> weakReference;
private PhantomReference<Object> phantomReference;
public void setO(Object o) {
this.o = o;
}
public Object getO() {
return this.o;
}
public void setWeakReference(Object o) {
this.weakReference = new WeakReference<>(o);
}
public Object getWeakReference() {
return this.weakReference.get();
}
public void setSoftReference(Object o) {
this.softReference = new SoftReference<>(o);
}
public Object getSoftReference() {
return this.softReference.get();
}
public void setPhantomReference(Object c) {
ReferenceQueue refQueue = new ReferenceQueue();
this.phantomReference = new PhantomReference<Object>(o, refQueue);
}
public Object getPhantomReference() {
return this.phantomReference.get();
}
}
public class B {
private A a;
public void setA(A a) {
this.a = a;
}
public A getA() {
return this.a;
}
public B(A a) {
this.a = a;
}
}
public class C {
public static void main(String[] args) {
A a = new A();
a.setO(new Object());
a.setSoftReference(new Object());
a.setWeakReference(new Object());
a.setPhantomReference(new Object());
B b = new B(a);
a = null;
// 触发回收
System.gc();
System.out.println(b.getA().getO());
System.out.println(b.getA().getSoftReference());
System.out.println(b.getA().getWeakReference());
System.out.println(b.getA().getPhantomReference());
}
}
运行结果:
上述的代码中,b对象是根,强引用a对象,a对象的四个属性对象分别是强、软、弱、幽灵引用,在回收过后,分别是存活、存活、被回收、被回收。