判断对象是否已经死亡回收:
1.引用计数算法:
给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。
//-XX:+PrintGC
public class ReferenceCountingGC {
public Object instance= null;
private static final int _1MB = 1024*1024;
private byte[] bigSize = new byte[2*_1MB];
public static void testGC() {
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
System.gc();
}
public static void main(String[] args) {
testGC();
}
}
引用计数算法的缺陷是:对象A和B已经不再使用,但是他们相互吸引,则他们不会被回收。
输出结果:
[GC (System.gc()) 6092K->600K(125952K), 0.0045186 secs]
[Full GC (System.gc()) 600K->529K(125952K), 0.0082995 secs]
输出结果显示了对象被回收了,说明hotspot不是采用这种算法来判断对象是否存货,我们看下一种算法。
2.可达性分析算法:
这算法的基本思 路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所 走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的.
GC Roots对象:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象。
2.方法区中静态类属性引用的对象。
3.方法区中常量引用的对象
4.本地方法栈中Native方法引用的对象。
真正宣告一个对象死亡,至少要经历两次标记。如果对象在可达性分析后发现没有与GC Roots相连接的引用链,那么它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为没有必要执行。
/**
*此代码演示了两点:
*1.对象可以在被GC时自我拯救。
*2.这种自救的机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次
*/
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
public void isAlive() {
System.out.println("yes,I am still alive:)");
}
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize method executed");
FinalizeEscapeGC.SAVE_HOOK = this;
}
public static void main(String[] args) throws Throwable {
SAVE_HOOK = new FinalizeEscapeGC();
//对象第一次成功拯救自己
SAVE_HOOK = null;
System.gc();
//因为finalize方法优先级很低,所以暂停0.5秒以等待它
Thread.sleep(500);
if(SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
}else {
System.out.println("no,I am dead:(");
}
//下面这段代码与上面的完全相同,但是这次自救却失败了
SAVE_HOOK = null;
System.gc();
//因为finalize方法优先级很低,所以暂停0.5秒以等待它
Thread.sleep(500);
if(SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
}else {
System.out.println("no,I am dead:(");
}
}
}
输出结果:
finalize method executed
yes,I am still alive:)
no,I am dead:(