Java对象利用finalize()方法逃避GC回收进行存活自救

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/u013632755/article/details/99618535

JVM判定对象是否存活

JVM判定对象是否死亡,是通过可达性分析算法来发现对象是否还存在与GC Root相连的引用链,如果没有相连的引用链,则进行第一次标记并且判断对象是否有覆盖finalize()方法或者是否调用过finalize()方法,如果没有覆盖或者没有调用过finalize()方法,那么JVM将判定对象已经死亡并进行回收。

如果对象覆盖了finalize()方法并且从来没有调用过,JVM会将该对象放入一个叫F-Queue队列中,并在稍后由一个由JVM自动创建的低优先级的Finalizer线程去执行它。JVM并不保证会等待finalize方法执行完毕。finalize()方法是对象逃脱GC的唯一一次机会,如果对象在该方法中重新与引用链上的任一对象建立了关联,那么JVM将会从待回收列表中移除该对象,否则该对象就没有机会逃脱被GC的命运了。

注意:
对象的finalize()方法只会被JVM执行一次,如果进行二次GC再次触发了该对象回收就不会再执行了,直接会回收掉。

并不鼓励使用finalize()方法,它运行代价高昂,不确定性大,无法保证各个对象的调用顺序。

对象利用finalize()逃脱内存回收例子

package test.vm;

public class FinalizeEscapeGC {
    public static FinalizeEscapeGC SAVE_HOOK;

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

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

        //由于finalize方法执行优先级很低,所以需要暂停0.5秒等待它执行
        Thread.sleep(500);
        if (SAVE_HOOK != null){
            System.out.println("I'am still alive");
        }else{
            System.out.println("I'am dead");
        }

        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500);
        if (SAVE_HOOK != null){
            System.out.println("I'am still alive");
        }else{
            System.out.println("I'am dead");
        }
    }
}

运行结果:

finalize method executed!
I'am still alive
I'am dead

猜你喜欢

转载自blog.csdn.net/u013632755/article/details/99618535