zoukankan      html  css  js  c++  java
  • 可达性分析算法

    在Java语言中,可作为GC Roots的对象包含以下几种:

    1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。(可以理解为:引用栈帧中的本地变量表的所有对象)
    2. 方法区中静态属性引用的对象(可以理解为:引用方法区该静态属性的所有对象)
    3. 方法区中常量引用的对象(可以理解为:引用方法区中常量的所有对象)
    4. 本地方法栈中(Native方法)引用的对象(可以理解为:引用Native方法的所有对象)

    可以理解为:

    (1)首先第一种是虚拟机栈中的引用的对象,我们在程序中正常创建一个对象,对象会在堆上开辟一块空间,同时会将这块空间的地址作为引用保存到虚拟机栈中,如果对象生命周期结束了,那么引用就会从虚拟机栈中出栈,因此如果在虚拟机栈中有引用,就说明这个对象还是有用的,这种情况是最常见的。

    (2)第二种是我们在类中定义了全局的静态的对象,也就是使用了static关键字,由于虚拟机栈是线程私有的,所以这种对象的引用会保存在共有的方法区中,显然将方法区中的静态引用作为GC Roots是必须的。

    (3)第三种便是常量引用,就是使用了static final关键字,由于这种引用初始化之后不会修改,所以方法区常量池里的引用的对象也应该作为GC Roots。最后一种是在使用JNI技术时,有时候单纯的Java代码并不能满足我们的需求,我们可能需要在Java中调用C或C++的代码,因此会使用native方法,JVM内存中专门有一块本地方法栈,用来保存这些对象的引用,所以本地方法栈中引用的对象也会被作为GC Roots。

    JVM之判断对象是否存活(引用计数算法、可达性分析算法,最终判定)

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

        即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历再次标记过程。
        标记的前提是对象在进行可达性分析后发现没有与GC Roots相连接的引用链。
      1).第一次标记并进行一次筛选。
        筛选的条件是此对象是否有必要执行finalize()方法。
        当对象没有覆盖finalize方法,或者finzlize方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”,对象被回收。

      2).第二次标记
        如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会被放置在一个名为:F-Queue的队列之中,并在稍后由一条虚拟机自动建立的、低优先级的Finalizer线程去执行。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束。这样做的原因是,如果一个对象finalize()方法中执行缓慢,或者发生死循环(更极端的情况),将很可能会导致F-Queue队列中的其他对象永久处于等待状态,甚至导致整个内存回收系统崩溃。
        Finalize()方法是对象脱逃死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模标记,如果对象要在finalize()中成功拯救自己----只要重新与引用链上的任何的一个对象建立关联即可,譬如把自己赋值给某个类变量或对象的成员变量,那在第二次标记时它将移除出“即将回收”的集合。如果对象这时候还没逃脱,那基本上它就真的被回收了。
    流程图如下:

  • 相关阅读:
    $Noip2011/Luogu1311$ 选择客栈
    $Noip2013/Luogu1970$ 花匠 $dp$+思维
    $CF1063B Labyrinth$ $01$最短路/$01BFS$
    $UVA10559 Blocks $区间$dp$
    $SCOI2009 windy$数 数位$dp$
    $cometoj#4 D $求和 不是$dp$
    Manacher算法总结
    题解 P1537 【弹珠】
    题解 P4609 【[FJOI2016]建筑师】
    字符串专题随笔
  • 原文地址:https://www.cnblogs.com/zdcsmart/p/12690978.html
Copyright © 2011-2022 走看看