精华内容
下载资源
问答
  • 2022-01-18 20:08:37

    看深入理解java虚拟机的时候看到3.2.4节生存还是死亡(to be or not to be)的时候看到的一段代码

    有趣分享给大家

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

    如果这个对象被判定为确有必要执行finalize()方法,那么该对象将会被放置在一个名为F-Queue的 队列之中,并在稍后由一条由虚拟机自动建立的、低调度优先级的Finalizer线程去执行它们的finalize() 方法。这里所说的“执行”是指虚拟机会触发这个方法开始运行,但并不承诺一定会等待它运行结束。 这样做的原因是,如果某个对象的finalize()方法执行缓慢,或者更极端地发生了死循环,将很可能导 致F-Queue队列中的其他对象永久处于等待,甚至导致整个内存回收子系统的崩溃。finalize()方法是对 象逃脱死亡命运的最后一次机会,稍后收集器将对F-Queue中的对象进行第二次小规模的标记,如果对 象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,譬如把自己 (this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移出“即将回收”的集 合;如果对象这时候还没有逃脱,那基本上它就真的要被回收了。从代码清单3-2中我们可以看到一个 对象的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 executed!");
            FinalizeEscapeGc.SAVE_HOOK = this;
        }
    
        public static void main(String[] args) throws InterruptedException {
            SAVE_HOOK = new FinalizeEscapeGc();
            //对象第一次成功拯救自己
            SAVE_HOOK = null;
            System.gc();
            /// 因为Finalizer方法优先级很低,暂停0.5秒,以等待它
            Thread.sleep(500);
            if (SAVE_HOOK != null) {//走进这里说明gc出发finalize了
                SAVE_HOOK.isAlive();
            } else {
                System.out.println("no, i am dead :(");
            }
            // 下面这段代码与上面的完全相同,但是这次自救却失败了
            SAVE_HOOK = null;
            System.gc();
            // 因为Finalizer方法优先级很低,暂停0.5秒,以等待它
            Thread.sleep(500);
            if (SAVE_HOOK != null) {
                SAVE_HOOK.isAlive();
            } else {//finalize只允许执行依次
                System.out.println("no, i am dead :(");
            }
    
        }
    }

    运行结果:

    我们在main方法中设置了SAVE_HOOK = null;相当于这个对象为null,当我们调用System.gc();垃圾回收的时候,虽然这个对象被认为是不可达的,但是因为覆盖了finalize()方法,所以会执行finalize()方法,当我们第二次调用System.gc();垃圾回收因为finalize()方法已经被执行了一遍了不能再执行所以此时真正认为该对象为垃圾对象。这就是上述的可达性分析的两次标记

    更多相关内容
  • 并发可达性分析遇到的问题 前面说完了可达性分析。基本对于垃圾回收如何判断对象是否存活便有了一个大概的认识。下面,我们补充一个知识点,并发可达性分析,也是为后面讲垃圾收集器做铺垫。 在JVM进行可达性分析时...
  • 交通可达性分析一般应用在城市路网优化、土地利用规划、地段评估、区位分析等方面,可以辅助规划编制。在构建了道路交通模型之后,可以利用ArcGIS计算O-D成本矩阵,通过选择合适的交通可达性模型计算可达性。本资源...
  • 连续可达性分析器(CORA)是MATLAB类的集合,用于使用可达性分析对网络物理系统进行形式验证。 CORA集成了各种矢量和矩阵集表示形式及其上的运算以及各种动态系统类的可达性算法。 该软件经过设计,可以交换设置表示...
  • 基于ArcGIS进行可达性分析详解,通过ArcGIS 工具进行数据处理,制作可达性分析图。
  • 基于ArcGIS 的交通可达性分析 摘要:交通可达性(accessibility)可简单地解释为利用特定交通系统,从某一 区位到达指定区位的便捷程度, 是评价交通网络和交通区位的常用手段。
  • 连续可达性分析器 (CORA) 是一组 MATLAB 类,用于使用可达性分析对网络物理系统进行形式验证。 CORA 集成了各种向量和矩阵集表示和对它们的操作以及各种动态系统类的可达性算法。 该软件的设计使得可以交换集合表示...
  • 道路可达性分析

    2018-12-05 17:06:36
    相信这里面的文档新手都能看得懂,反正我这个菜鸟是看懂了
  • 可达性分析

    2014-04-23 19:19:22
    ARCGIS 交通 可达性分析 韶关市 路网易达行
  • 因此,提出了扩展颜色逻辑Petri网模型及其可达性分析方法。首先,为了方便可达标识的表示和计算,引入多重集的素数表示法,用素数幂的乘积来表示一个多重集,并给出了判断变迁使能的方法。其次,通过定义颜色逻辑关联矩阵,...
  • 在这里,我们提出了一种基于可达性分析(RA)的 TOPP 新方法。 关键见解是通过求解小型线性规划 (LP) 递归地计算路径上离散位置处的可达和可控集。 由此产生的算法比基于 NI 的方法更快,并且与基于 CO 的方法一样...
  • 文章以北京市六环以内城市公园作为研究对象,运用GIS网络分析法结合道路、建筑、人口等大数据对北京市二环—六环不同环线内城市公园的可达性及其服务状况进行研究.结果表明:(1)整体上,公园步行可达面积比为35.76%,...
  • mnist代码DeepGO:具有可证明保证的深度神经网络的可达性分析 具有可证明保证的深度神经网络的可达性分析 作者:阮文杰,黄晓伟,玛塔·克瓦特柯夫斯卡(Marta Kwiatkowska) 第27届国际人工智能联合会议(IJCAI'18...
  • 基于ArcGIS的可达性分析[汇编].pdf
  • Petri网的可达性判定问题是进行Petri网分析的基础。通过分析目前求解Petri网可达问题的判定方法和基于约束程序的Petri网可达问题判定方法,提出一种基于约束优化的Petri网可达问题判定方法,该方法是在状态方程法的...
  • 基于ArcGIS和Python集成开发可达性分析工具的研究.pdf
  • 基于ArcGIS进行可达性分析数据,制作ArcGIS Server发布地图数据,进行可达性分析
  • 掌握栅格数据的可达性分析方法

    目录

    一、实验名称

    二、实验准备

    1.实验原理

    2.实验背景

    3.实验目的:

    4.数据准备

    三、实验步骤


    文章数据免费下载

    一、实验名称

            栅格数据空间分析之可达性分析

    二、实验准备

    1.实验原理

            可达性用于测度区域内一点到最近旅游景点所花费的时间表征区内游客到景点的便利程度,有助于厘清旅游景点和交通网络之间的关系,计算公式如下:

    A_{i} = min(M_{i}T_{ij})

    式中:i、j 为示范区内的景点;Tij 为点i 在交通网络中通行最短的路线到达景点j 的通行时间;Mj 为景点j的权重,若只研究交通通达性则数值为1;Ai 为示范区内点i 的可达性。

            本研究基于交通路网测算示范区的可达性,测算方法是用1 km×1 km栅格网将原矢量底图栅格化,根据国家规定的不同路网的通行速度,并参考前人研究成果,高速铁路、普通铁路、高速、国道、省道、县道的速度分别设为250、100、100、80、60、40 km/h,计算路网通行时间,并赋予栅格相应的时间成本值,在此基础上对路网成本栅格图像采用最短成本加权距离,算出示范区内各点到景点的可达性。为了从整体上反映旅游景点可达性在行政单元区域层面的空间结构状态,更为直接地刻画区域内游客日常出游的便利程度,通过计算示范区县级单元内栅格景点可达性的均值来反映整个县级单元的景点可达性。

             式中:Rj为第j 个县级单元的整体景点可达性;Ai为县级单元第i 个网格的景点可达性;nj为落在第j 个县级单元范围内网格的总数。

            不同类别景点可达性分布频率和累计频率统计表计算。

    1 各时间段可达性分布频率 = 各时间段可达性面积/总面积

    2 累计频率 =各时间段可达性分布频率的和

    3 县域单元的整体可达性等级分布分别统计不同时间段的可达性的景点的个数

    2.实验背景

            现有一城市道路数据road.shp,和一所医院的位置数据hospital.shp。道路数据中记录了每一段路的长度(m),车辆行驶的平均时速(m/min)和所需的时间(min)。假设在没有道路的区域,人平均走路的速度是80m/min(field.shp)。求出在30分钟内可到达该医院的可达性范围。

    3.实验目的:

            掌握栅格数据的可达性分析方法

    4.数据准备

    1 road.shp:道路线要素数据

    2 hospital.shp:医院点要素数据

    3 field.shp:非道路面要素数据

    三、实验步骤

            1.新建ArcMap空白文档,导入以上数据,然后我们将road.shp、field.shp数据转为栅格数据,打开ArcToolBox工具箱,选择转换工具>转为栅格>折线转栅格,输入要素为road.shp,值字段选择speed,更改输出路径,点击确定即可输出。

     

     

     

            2.接下来将面转为栅格,打开面转栅格工具,输入数据为field.shp,值字段为speed,更改输出路径,确定即可输出;

     

     

            3.接下来,我们创建耗时栅格,打开栅格计算器,输入 1.0/’road.shp’,更改输出路径,点击确定即可,同理处理field.shp;

     

     

            4.接着,我们需要将两个耗时栅格结合为一个,打开镶嵌至新栅格,输入要素为之前的两个耗时栅格,设置输出位置与数据名称,波段数为1,镶嵌运算符为minmum,点击确定即可;

     

             5.我们进行成本距离分析,打开成本距离工具,输入要素源数据为hospital.shp,成本距离为耗时栅格cost,更改输出路径与数据名称,点击确定输出,打开distance属性,更改分类类型为手动,分类数为2,分类阈值为10,适当调整颜色,点击确定,我们即可得到最终结果;

     

     

     


     

    如果觉得我的文章对您有帮助,三连+关注便是对我创作的最大鼓励!

    更多GIS空间分析文章

     “本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_45590504/category_11750215.html百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。”

    展开全文
  • 可达性分析之三色标记算法详解

    千次阅读 多人点赞 2021-03-28 16:14:13
    CMS算法的基础是通过可达性分析找到存活的对象,然后给存活的对象打个标记,最终在清理的时候,如果一个对象没有任何标记,就表示这个对象不可达,需要被清理。 并发标记阶段是从GC Root直接关联的对象开始枚举的

    本文是博主基于自己理解所写,可能与虚拟机具体实现有部分差异,三色标记是个基础算法,不同的产品落地也都可能有不同的实现

    一、三色标记算法

      在CMS垃圾收集器中提到了,在CMS的并发清理阶段才产生的垃圾对象,会被当做浮动垃圾,留到下一次GC再清理。其实在并发标记阶段,由于用户线程在并发运行,也可能会导致引用关系发生改变,导致标记结果不准确,从而引发更加严重的问题,这些发生变更的数据会在重新标记阶段被处理,那么会出现什么问题?又是如何处理的呢?
      CMS算法的基础是通过可达性分析找到存活的对象,然后给存活的对象打个标记,最终在清理的时候,如果一个对象没有任何标记,就表示这个对象不可达,需要被清理,标记算法就是使用的三色标记。并发标记阶段是从GC Root直接关联的对象开始枚举的过程。
      对于三色标记算法而言, 对象会根据是否被访问过(也就是是否在可达性分析过程中被检查过)被分为三个颜色:白色灰色黑色

    • 白色:这个对象还没有被访问过,在初始阶段,所有对象都是白色,所有都枚举完仍是白色的对象将会被当做垃圾对象被清理。
    • 灰色:这个对象已经被访问过,但是这个对象所直接引用的对象中,至少还有一个没有被访问到,表示这个对象正在枚举中。
    • 黑色:对象和它所直接引用的所有对象都被访问过。这里只要访问过就行,比如A只引用了B,B引用了C、D,那么只要A和B都被访问过,A就是黑色,即使B所引用的C或D还没有被访问到,此时B就是灰色。

      根据这些定义,我们可以得出:

    • 在可达性分析的初始阶段,所有对象都是白色,一旦访问了这个对象,那么就变成灰色,一旦这个对象所有直接引用的对象都访问过(或者没有引用其它对象),那么就变成黑色
    • 初始标记之后,GC Root节点变为黑色(GC Root不会是垃圾),GC Root直接引用的对象变为灰色
    • 正常情况下,一个对象如果是黑色,那么其直接引用的对象要么是黑色,要么是灰色,不可能是白色(如果出现了黑色对象直接引用白色对象的情况,就说明漏标了,就会导致对象误删,后面会介绍如何解决),这个特性也可以说是三色标记算法正确性保障的前提条件。

      算法大致的流程是(初始状态所有对象都是白色):

    1. 首先我们从GC Roots开始枚举,它们所有的直接引用变为灰色,自己变为黑色。可以想象有一个队列用于存储灰色对象,会把这些灰色对象放到这个队列中
    2. 然后从队列中取出一个灰色对象进行分析:将这个对象所有的直接引用变为灰色,放入队列中,然后这个对象变为黑色;如果取出的这个灰色对象没有直接引用,那么直接变成黑色
    3. 继续从队列中取出一个灰色对象进行分析,分析步骤和第二步相同,一直重复直到灰色队列为空
    4. 分析完成后仍然是白色的对象就是不可达的对象,可以作为垃圾被清理
    5. 最后重置标记状态

      前面的描述都比较抽象,这里以一个例子进行说明,假设现在有以下引用关系:
    在这里插入图片描述
      首先,所有GC Root的直接引用(A、B、E)变为灰色,放入队列中,GC Root变为黑色:
    在这里插入图片描述
      然后从队列中取出一个灰色对象进行分析,比如取出A对象,将它的直接引用C、D变为灰色,放入队列,A对象变为黑色:
    在这里插入图片描述
      继续从队列中取出一个灰色对象,比如取出B对象,将它的直接引用F变为灰色,放入队列,B对象变为黑色:
    在这里插入图片描述
      继续从队列中取出一个灰色对象E,但是E对象没有直接引用,变为黑色:
    在这里插入图片描述
      同理依次取出C、D、F对象,他们都没有直接引用,那么变成黑色(这里就不一个一个的画了):
    在这里插入图片描述
      到这里分析已经结束了,还剩一个G对象是白色,证明它是一个垃圾对象,不可访问,可以被清理掉。

    二、并发标记带来的问题

      如果整个标记过程是STW的,那么没有任何问题,但是并发标记的过程中,用户线程也在运行,那么对象引用关系就可能发生改变,进而导致两个问题出现。

    2.1 非垃圾变为了垃圾

      比如我们回到上述流程中的这个状态:
    在这里插入图片描述
      此时E对象已经被标记为黑色,表示不是垃圾,不会被清除。此时某个用户线程将GC Root2和E对象之间的关联断开了(比如 xx.e=null;):
    在这里插入图片描述
      后面的图就不用画了,很显然,E对象变为了垃圾对象,但是由于已经被标记为黑色,就不会被当做垃圾删除,姑且也可以称之为浮动垃圾

    2.2 垃圾变为了非垃圾

      如果上面提到的浮动垃圾你觉得没啥所谓,即使本次不清理,下一次GC也会被清理,而且并发清理阶段也会产生所谓的浮动垃圾,影响不大。但是如果一个垃圾变为了非垃圾,那么后果就会比较严重。比如我们回到上述流程中的这个状态:
    在这里插入图片描述
      标记的下一步操作是从队列中取出B对象进行分析,但是这个时候GC线程的时间片用完了,操作系统调度用户线程来运行,而用户线程先执行了这个操作:A.f = F;那么引用关系变成了:
    在这里插入图片描述
      接着执行:B.f=null;那么引用关系变成了:
    在这里插入图片描述
      好了,用户线程的事儿干完了,GC线程重新开始运行,按照之前的标记流程继续走:从队列中取出B对象,发现B对象没有直接引用,那么将B对象变为黑色:
    在这里插入图片描述
      接着继续分别从队列中取出E、C、D三个灰色对象,它们都没有直接引用,那么变为黑色对象:
    在这里插入图片描述
      到现在所有灰色对象分析完毕,你肯定已经发现问题了,出现了黑色对象直接引用白色对象的情况,而且虽然F是白色对象,但是它是垃圾吗?显然不是垃圾,如果F被当做垃圾清理掉了,那就GG~

    三、增量更新和原始快照(SATB)

      上面一共出现了两个问题,从结果上来看,可以这样描述:

    • 一个本应该是垃圾的对象被视为了非垃圾
    • 一个本应该不是垃圾的对象被视为了垃圾

      对于第一个问题,我们前文也提到了,即使不去处理它也无所谓,大不了等到下次GC再清理。最重要的是第二个问题,如果误清理了正在被使用的对象,那就是实打实的BUG了。那么如何解决这个问题呢?
      出现这个问题的主要原因是,一个对象从被B引用,变更为了被A引用。那么对于A来说就是多了一个直接引用,对于B来说就是少了一个直接引用。我们可以从这两个方面入手来解决这个问题,对应了也有两个方案,分别是增量更新(Incremental Update)原始快照(SATB,Snapshot At The Beginning)

    3.1 读写屏障

      在这讲述解决方案之前,要描述两个名词:读屏障写屏障。注意,这里的屏障和并发编程中的屏障是两码事儿。这里的屏障很简单,可以理解成就是在读写操作前后插入一段代码,用于记录一些信息、保存某些数据等,概念类似于AOP。

    3.2 增量更新

      增量更新是站在新增引用的对象(也就是例子中的A对象)的角度来解决问题。所谓增量更新,就是在赋值操作之前添加一个写屏障,在写屏障中记录新增的引用。比如,用户线程要执行:A.f = F;那么在写屏障中将新增的这个引用关系记录下来。标准的描述就是,当黑色对象新增一个白色对象的引用时,就通过写屏障将这个引用关系记录下来。然后在重新标记阶段,再以这些引用关系中的黑色对象为根,再扫描一次,以此保证不会漏标。
      在我们这个例子中,在并发标记阶段,A是一个黑色对象,F是一个白色对象,A引用了F,这个引用关系会被记录下来,然后通过这个记录在重新标记阶段再从A对象开始枚举一次,保证如果A还是保持着F的引用,那么F会被正确标记;如果A到F的引用在并发标记阶段又断开了,此次枚举也无法访问到它,活该被清除。
      要实现也很简单,在重新标记阶段直接把A对象(和其它有相同情况发生的对象)变为灰色,放入队列中,再来一次枚举过程。要注意,在重新标记阶段如果用户线程还是继续执行,那么这个GC永远可能也做不完了,所以重新标记需要STW,但是这个时间消耗不会太夸张。如果实在重新标记阶段耗时过长,那么可以尝试在重新标记之前做一次Minor GC,这个在CMS垃圾收集器中有介绍,这里就不赘述了。

    3.3 原始快照(SATB)

      原始快照是站在减少引用的对象(也就是例子中的B对象)的角度来解决问题。所谓原始快照,简单的讲,就是在赋值操作(这里是置空)执行之前添加一个写屏障,在写屏障中记录被置空的对象引用。比如,用户线程要执行:B.f=null;那么在写屏障中,首先会把B.f记录下来,然后再进行置空操作。记录下来的这个对象就可以称为原始快照。
      那么记录下来之后呢?很简单,之后直接把它变为黑色。意思就是默认认为它不是垃圾,不需要将其清理。当然,这样处理有两种情况,一种情况是,F的确不是垃圾,直到清理的那一刻,都仍然有至少一个引用链能访问到它,这没有什么问题;另一种情况就是F又变成了垃圾。在上述的例子中,就是A到F的引用链也断了,或者直接A都成垃圾了,那F对象就成了浮动垃圾。对于浮动垃圾,前面不止一次就提到了,直接不用理会,如果到下一次GC时它仍然是垃圾,自然会被清理掉。

    3.4 方案抉择

      从增量更新和原始快照的实现(理论上)就可以发现,原始快照相比于增量更新来说效率会更高,因为不用在重新标记阶段再去做枚举遍历,但是也就可能会导致有更多的浮动垃圾。G1使用的就是原始快照,CMS使用的是增量更新。
      既然原始快照可能会有更严重的浮动垃圾问题,那么为什么不使用增量更新呢?原因可能很简单,就是因为简单。想象一下,G1虽然也是基于年轻代和老年代的分代收集算法,但是年轻代和老年代被弱化为了逻辑上,其所管理的内存被划分为了很多region,对象跨代引用带来的问题在G1中要比传统的分代收集器更加突出,虽然有Remember Set方案缓解,但是相对来说在重新标记阶段进行再次遍历枚举的代价会大很多。最重要的是,重新标记(最终标记)阶段是会STW的,如果这个阶段花费太多的时间去做可达性分析,那么就违背了G1低延时的理念。当然这个是博主的猜测,如果读者朋友有更好的想法,欢迎提出。

    四、总结

      这里有一个需要注意的点,重新标记阶段会STW,以此保证标记结果的正确性(主要是漏标)。到现在你可能理解了,垃圾收集器中所描述的:并发清理阶段产生的垃圾会被当做浮动垃圾,只能留待下一次GC被清理。那么实际上是怎么回事呢?其实就很简单了,只要在并发清理阶段产生的对象,直接就认为是黑色对象,全部都不是垃圾。如果一个对象最终成了垃圾,那它就是浮动垃圾,如果没成垃圾,那么标记为黑色也没有什么问题。因为到了清理阶段,标记工作已经完成,没有办法再找到合适的方式去处理这个问题,不然一次GC可能永远也结束不了。
      话说回来,对于上面漏标的情况,你可能还有一个疑问:在并发标记过程中,除了引用关系发生变更的情况,如果用户线程直接创建了一个新对象,这个对象默认是白色,又直接和黑色对象关联,那又该当如何呢?也就是白色对象可能是从其他对象的引用链上”转移“过来的,也可能就是一个新对象。其实可以想象的到,对于新对象加入到黑色节点,我们无法使用原始快照,但是可以使用增量更新,或者直接简单处理,和并发清理阶段一样:在这期间创建的新对象都认为不是垃圾(比如标记为黑色),如果成了垃圾,那就是浮动垃圾,还是留待下一次GC处理。总之,标记的总体原则就是,“另可放过,不可杀错”。
      关于黑白灰三个颜色,是一个抽象的概念,虽然使用可达性分析的垃圾收集器基本都采取三色标记的思想,但在实现上可能也各不相同,像如何标识颜色、灰色队列如何实现等等。比如不止Java,在go的GC中也实现了三色标记算法。个人认为作为普通开发人员,理解思想就够了,如果要看具体的实现,就需要具体到实际的实现源码中去探寻。

    如有错误,感谢指出!

    展开全文
  • 可达性分析算法

    千次阅读 2021-07-21 18:54:27
    可达性分析算法:也可以称为根搜索算法、追踪性垃圾收集。 相对于引用计数算法而言,可达性分析算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效地解决在引用计数算法中循环引用的问题,防止...

    一 概念

    可达性分析算法:也可以称为根搜索算法、追踪性垃圾收集。

    相对于引用计数算法而言,可达性分析算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效地解决在引用计数算法中循环引用的问题,防止内存泄漏的发生。

    相较于引用计数算法,这里的可达性分析就是 Java、C# 选择的。这种类型的垃圾收集通常也叫作追踪性垃圾收集(Tracing Garbage Collection)。

    二 思路

    所谓 "GC Roots”根集合就是一组必须活跃的引用。

    基本思路:

    • 可达性分析算法是以根对象集合(GCRoots)为起始点,按照从上至下的方式搜索被根对象集合所连接的目标对象是否可达。

    • 使用可达性分析算法后,内存中的存活对象都会被根对象集合直接或间接连接着,搜索所走过的路径称为引用链(Reference Chain)。

    • 如果目标对象没有任何引用链相连,则是不可达的,就意味着该对象己经死亡,可以标记为垃圾对象。

    • 在可达性分析算法中,只有能够被根对象集合直接或者间接连接的对象才是存活对象。

    三 GC Roots 可以是哪些?

    • 虚拟机栈中引用的对象

               比如:各个线程被调用的方法中使用到的参数、局部变量等。

    • 本地方法栈内 JNI(通常说的本地方法)引用的对象

    • 方法区中类静态属性引用的对象

               比如:Java类的引用类型静态变量

    • 方法区中常量引用的对象

               比如:字符串常量池(string Table)里的引用

    • 所有被同步锁 synchronized 持有的对象

    • Java虚拟机内部的引用。

               基本数据类型对应的 Class 对象,一些常驻的异常对象(如:NullPointerException、OutOfMemoryError),系统类加载器。

    • 反映 java 虚拟机内部情况的 JMXBean、JVMTI 中注册的回调、本地代码缓存等。

    四 总结

    总结一句话就是,堆空间外的一些结构,比如虚拟机栈、本地方法栈、方法区、字符串常量池等地方对堆空间进行引用的,都可以作为 GC Roots 进行可达性分析。

    除了这些固定的 GC Roots 集合以外,根据用户所选用的垃圾收集器以及当前回收的内存区域不同,还可以有其他对象“临时性”地加入,共同构成完整 GC Roots 集合。比如:分代收集和局部回收(Partial GC)。

    如果只针对 Java 堆中的某一块区域进行垃圾回收(比如:典型的只针对新生代),必须考虑到内存区域是虚拟机自己的实现细节,更不是孤立封闭的,这个区域的对象完全有可能被其他区域的对象所引用,这时候就需要一并将关联的区域对象也加入 GCRoots 集合中去考虑,才能保证可达性分析的准确性。

    五 小技巧

    由于 Root 采用栈方式存放变量和指针,所以如果一个指针,它保存了堆内存里面的对象,但是自己又不存放在堆内存里面,那它就是一个 Root。

    六 注意

    如果要使用可达性分析算法来判断内存是否可回收,那么分析工作必须在一个能保障一致性的快照中进行。这点不满足的话分析结果的准确性就无法保证。

    这点也是导致 GC进行时必须“stop The World”的一个重要原因。

    即使是号称(几乎)不会发生停顿的 CMS 收集器中,枚举根节点时也是必须要停顿的。

    展开全文
  • Java并不采用引用计数法来判断对象是否已“死”,而采用“可达性分析”来判断对象是否存活(同样采用此法的还有C#、Lisp-最早的一门采用动态内存分配的语言)。 此算法的核心思想:通过一系列称为“GC Roots”的...
  • JVM:可达性分析算法

    千次阅读 2019-09-03 23:21:11
    一、可达性分析算法 在Java中,是通过可达性分析(Reachability Analysis)来判定对象是否存活的。该算法的基本思路就是通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过的路径...
  • 与引用计数相比,可达性分析的的一些不同:可达性分析算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效地解决在引用计数器算法中循环利用的问题,防止内存泄露的发生 (3).基本思路: 1).可达性...
  • 可达性分析详解

    千次阅读 2020-08-29 14:55:10
    主要思路 可达性分析算法的主要思路是先找出一批根节点对象集合作为GC Roots(可称为根节点枚举),然后从这批根节点出发,查找其引用关系(类似于深度优先搜索),最终形成如下图这样的反映对象间依赖关系的图,若...
  • 大白话理解可达性分析算法

    万次阅读 多人点赞 2020-10-24 21:39:29
    可达性分析算法 引用计数算法 在对象中添加一个引用计数器,每当新加一个引用时,计数器就加1,当引用失效时,计数器就减1。任何时刻只要计数器为0就代表对象没有引用可以被回收。 这种算法实现简单,判断高效,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 30,841
精华内容 12,336
关键字:

可达性分析