美文网首页Java
垃圾回收算法(2)-根搜索算法

垃圾回收算法(2)-根搜索算法

作者: 一觉睡到丶小时候 | 来源:发表于2020-07-09 09:23 被阅读0次

前言

相对于引用计数算法而言,根搜索算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效的解决在引用记数法中一些已经死亡的对象因为相互引用而导致的无法正确被
标记的问题,防止内存泄漏的发生。

算法原理

根搜索算法是以根对象集合为起始点,按照从上至下的方式搜索被根对象集合所连接的目标对象是否可达(使用根算法后,内存中的存活对象都会被根对象集合直接或间接连接着)
如果目标对象不可达,就意味着该对象已经死亡,便可将其标记为垃圾对象。

在根搜索算法中不可达的对象,也并非是“非死不可”,这时候他们暂时处于“缓行”阶段,要真正宣告一个对象死亡,至少要经历2次标记过程。如果对象在进行根搜索后发现并没有与GC Roots相连接的
引用链,那么它将会被第一次标记并进行一次筛选,筛选的条件是这个对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,
虚拟机将这两种情况都视为没有必要执行finalize()方法。如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会被放置在一个名为F-Queue的队列之中,并在稍后有一条虚拟机自动建立、
低优先级的 finalize的线程去执行。虚拟机会触发finalize()方法,但并不承诺等待它执行结束。finalize()方法是对象逃脱死亡的最后一次F-Queue中的对象机会。GC将会对F-QUEUEF-Queue中的对
象进行第二次小规模的标记,如果某个对象重新与GC Roots引用链上的对象建立关联关系,那么第二次标记时它将被移除F-Queue。如果对象这个时候还没有逃脱,那他就真的离死不远了。

image

就拿上图来说,ObjectD和ObjectE是互相关联的,但是由于GC roots到这两个对象不可达,所以最终D和E还是会被当做GC的对象,上图若是采用引用计数法,则A-E五个对象都不会被回收。

逃脱回收实验

public class FinalizeEscapeGC {

    public static FinalizeEscapeGC SAVE_HOOK = null;
    
    public void isAlive(){
        System.out.println("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 InterruptedException {
        SAVE_HOOK = new FinalizeEscapeGC();
        //对象第一次拯救自己
        SAVE_HOOK = null;
        System.gc();
        //因为Finalize方法的优先级很低,暂停5秒
        Thread.sleep(500);
        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("i am dead");
        }
        //以下代码与上面的完全相同,但是这次却自救失败了
        SAVE_HOOK = null;
        System.gc();
        //因为Finalize方法的优先级很低,暂停5秒
        Thread.sleep(500);
        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("i am dead");
        }
    }
}

控制台输出

finalize method executed
i am still alive
i am dead

从代码的运行结果看出,SAVE_HOOK对象的finalize()方法确实被GC收集器出发过,并且在被手机前成功逃脱了。另一个值得注意的地方是,代码中有2段完全一样的代码,执行结果是一次成功,一次失败,
这是因为热河一个对象的finalize()方法都会被系统自动调用一次,如果对象面临下一次回收,他的finalize()方法不会被再次执行,因此后面的方法执行自救失败了。

个人博客
腾讯云社区
掘金
CSDN
公众号:

wx.jpg

相关文章

  • 垃圾回收算法(2)-根搜索算法

    前言 相对于引用计数算法而言,根搜索算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效的解决在引用...

  • 一文了解JVM全部垃圾回收器,从Serial到ZGC

    《对象搜索算法与回收算法》介绍了垃圾回收的基础算法,相当于垃圾回收的方法论。接下来就详细看看垃圾回收的具体实现。 ...

  • 一文了解JVM全部垃圾回收器,从Serial到ZGC

    《对象搜索算法与回收算法》介绍了垃圾回收的基础算法,相当于垃圾回收的方法论。接下来就详细看看垃圾回收的具体实现。 ...

  • 23. java虚拟机总结-和OOM相关的 (六)

    垃圾回收算法 可达性分析法(根搜索算法,GC ROOTS) 从 GC Roots 向下追溯、搜索,会产生一个叫作 ...

  • Android内存泄漏总结和leakcanary使用

    什么是内存泄漏? Android虚拟机的垃圾回收采用的是根搜索算法。GC会从根节点(GC Roots)开始对hea...

  • Java的四种引用

    首先,Java的垃圾回收机制无论是通过引用计数算法判断对象的引用数量还是通过根搜索算法判断对象的引用链是否可达,判...

  • JVM垃圾回收

    一.什么样的需要回收 1.计数法:循环引用的问题不好解决 2.根搜索算法,根节点无法触达的对象,将被回收 - ...

  • JVM垃圾回收

    GC垃圾回收流程 垃圾收集算法 垃圾回收算法 引用类型 垃圾回收的时机 1.垃圾收集算法 (1).引用计数算法含义...

  • JVM垃圾回收算法

    Java基础:JVM垃圾回收算法 [toc] 参考:Java基础:JVM垃圾回收算法图解JVM垃圾回收算法 总结:...

  • JVM的4种垃圾回收算法、垃圾回收机制与总结

    垃圾回收算法 1.标记清除 标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。 在标记阶段首先通过根节点(...

网友评论

    本文标题:垃圾回收算法(2)-根搜索算法

    本文链接:https://www.haomeiwen.com/subject/xrcjcktx.html