GC判断对象是否存活

判断对象是否已经死亡回收:
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()方法已经被虚拟机调用过,虚拟机将这两种情况都视为没有必要执行。

/** 
 *此代码演示了两点:
 *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:(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值