GC判断可回收对象算法

声明:本文摘录周志明先生的《深入理解Java虚拟机》,记录下GC算法中的可达性算法分析。是在问答频道看到一个对可达性算法的疑问,梳理下,也是自我学习巩固的过程。关于可达性算法的几点记录如下:

   首先,可达性算法基本思路是定义一些列称为"GC-Roots"的对象作为起始阶段,从这些节点向下搜索,搜索走过的路径称为引用链,当一个对象到GCRoots没有任何引用链时(即从GCRoots到这个对象不可达),则证明此对象是不可用的。
    其次,可达性算法中的不可达对象,在真正宣告“死亡”需要回收之前,至少要经过两轮标记过程:如果对象不可达,会被第一次标记并且进行一次筛选,筛选条件是此对象有没有必要执行finalize()方法。当对象没有覆盖finalize()方法或者这个方法以及被执行过了,那么就视为没有必要再执行。
   对于那些有必要执行finalize()方法的对象会被放在一个队列F-Queue中,稍后由虚拟机的一个线程去执行逐一执行队列中对象的finalize方法,如果线程在执行过程中发生了死循环,或者某个对象的finalize方法执行时间过长,导致队列中其他对象一直处于等待,那么就会导致整个内存回收系统崩溃。
   第三,finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC会对F-Queue中的对象进行第二次小规模的标记,如果能在finalize中成功重新引用,第二次标记时就会将该对象从F-Queue集合中移除,而成功脱逃。
   所以,我理解的循环引用可能是想说不可达后突然又再次引用了,那么只能在finalize方法中再次引用而救活对象了。如果是普通循环中的循环操作引用,应该还没有涉及到垃圾回收、标记不可达的时候。
   最后,算法中的根对象通常是全局的静态成员对象,方法区中的常量引用对象,Native引用对象,线程栈中的引用对象等。
   附上一个可达性算法中笫二次标记自我复活的例子:
/**
 * 自我救赎的机会只有一次,即重新finalize并再次引用自己,
 * 因为一个对象的 finalize()方法最多只会被系统调用一次
 *
 */
public class FinalizeEscapeGC {
    public static FinalizeEscapeGC save_hook = null;

    public void isAlive() {
        System.out.println("yes ,I am still alive.");
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("finalize method executd!");
        FinalizeEscapeGC.save_hook = this;
    }

    public static void main(String[] args) throws Throwable {
        save_hook = new FinalizeEscapeGC();

        // 设置为null,标记不可达,通知GC回收
        save_hook = null;
        System.gc();

        // 当前线程休眠5秒,让GC线程优先执行
        Thread.sleep(500);
        if (save_hook != null) {
            //finalize()中自引用成功,该分支执行了
            save_hook.isAlive();
        } else {
            System.out.println("first .Oh My God ,I am going to dead.Who can help me?");
        }

        // 再测试一次:下面代码与上面完全相同,但是自我救赎失败,因为finalize只会执行一次
        save_hook = null;
        System.gc();

        // 当前线程休眠5秒,让GC线程优先执行
        Thread.sleep(500);
        if (save_hook != null) {
            save_hook.isAlive();
        } else {
            //已经执行过finalize()了,不能再逃脱回收命运了
            System.out.println("second Oh My God ,I am going to dead.Who can help me?");
        }
    }
}

测试结果可以看到对象能够完成一次在finalize中的自我复活,但是也仅有这一次机会,最终还是逃不脱GC的命运。

已标记关键词 清除标记
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页
实付 9.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值