判断对象是否可以被回收的算法

引用计数算法Reference Counting:给对象添加一个引用计数器,每当被引用一次的时候计数器值+1,当引用失效时计数器值-1,任何时刻计数器为0的对象就是不可能再被使用的。存在问题:解决不了对象之间相互循环引用的问题

public class ReferenceCountingGC {
    public Object instance;
    public static void main(String[] args) throws InterruptedException {
        ReferenceCountingGC refA = new ReferenceCountingGC();
        ReferenceCountingGC refB = new ReferenceCountingGC();
        refA.instance = refB;
        refB.instance = refA;
        refA = null;
        refB = null;
        System.gc();
        Thread.sleep(10000); //gc回收需要时间
    }
    @Override
    protected void finalize() throws Throwable {
        System.out.println("被回收前执行finalize,finalize方法优先级很低");
        super.finalize();
    }
}

可达性分析算法Reachability Analysis:将GC Roots对象作为起始点,从这些起始点开始往下搜索,搜索所走过的路径称之为引用链Reference Chain,当一个对象到GC Roots没有任何引用链相连时则说明此对象是不可达的,需要被gc回收

GC Roots包含:虚拟机栈(栈帧中的本地变量表)中引用的对象;

  方法区中静态属性引用的对象;

  方法区中常量引用的对象;

  本地方法栈中JNI(native方法)引用的对象

finalize()方法最终判定对象是否存活

即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历再次标记过程

标记的前提是对象在进行可达性分析后发现没有与GC Roots相连接的引用链。

1. 第一次标记并进行一次筛选。

筛选的条件是此对象是否有必要执行finalize()方法。

当对象没有覆盖finalize方法,对象将直接被回收。

2. 第二次标记

如果这个对象覆盖了finalize方法,finalize方法是对象脱逃死亡命运的最后一次机会,如果对象要在finalize()中成功拯救自己,只要重新与引用链上的任何的一个对象建立关联即可,譬如把自己赋值给某个类变量或对象的成员变量,那在第二次标记时它将移除出“即将回收”的集合。如果对象这时候还没逃脱,那基本上它就真的被回收了

注意:一个对象的finalize()方法只会被执行一次,也就是说通过调用finalize方法自我救命的机会就一次。

对象自救:

public class FinalizeEscapeGC {
    private static FinalizeEscapeGC SAVE_HOOK = null;
    public static void main(String[] args) {
        SAVE_HOOK = new FinalizeEscapeGC();
        SAVE_HOOK = null;
        System.gc();
        try {

    Thread.sleep(2000); //finalize优先级低,暂停2s等待gc
        } catch (InterruptedException e) { e.printStackTrace(); }
        if (SAVE_HOOK != null) { System.out.println("i am still alive!");
        } else { System.out.println("sorry, i am not alive"); }
        SAVE_HOOK = null;
        System.gc();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (SAVE_HOOK != null) { System.out.println("i am still alive!");
        } else { System.out.println("sorry, i am not alive");}
    }
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("对象在被gc时可以自我拯救,这种自救的机会只有一次,因为一个对象的finalize方法最多只会被系统自动调用一次");
        SAVE_HOOK = this;
    }
}

打印结果如下:

对象在被gc时可以自我拯救,这种自救的机会只有一次,因为一个对象的finalize方法最多只会被系统自动调用一次

i am still alive!

sorry, i am not alive

猜你喜欢

转载自blog.csdn.net/qq_33436466/article/details/108462204