zoukankan      html  css  js  c++  java
  • 垃圾回收算法之引用跟踪算法

          在《垃圾回收算法之引用计数算法》这篇博客里,我们说到了引用计数算法的缺陷:会造成循环引用的问题。本篇的引用跟踪算法则客服了这种缺陷。

          在引用计数算法中,对于每个引用的对象,我们有一个额外的字段专门计数这个对象被引用的次数,当次数为0时,则视为垃圾。那在引用跟踪算法中,我们如何判断这个对象是垃圾呢?答案是:对象可达图。

    一.对象可达图

           它的含义是,首先将所有的对象标记为垃圾并将它们视为根,从根出发,将所有的正在使用的对象串联起来,直至完毕,不被串联的对象即为“不可达”,即被视为垃圾,”可达” 的对象则被认为是有用的,在垃圾回收的过程中幸存下来。      

    static void Main(string[] args)
    {
       var obj1 = new object();//step1
       DoSomething();//step2
       var obj3 = obj1;//step3  
    }//step4
    
    static void DoSomething()
    {
       var obj2 = new object();
    }

          我们来看下面一段代码,根据可达图的含义来画出对象可达图。从总体来看彼此的调用关系如下:

          

           我们假设,在运行到step3之后,运行step4之前,进行了一次垃圾回收。

           首先:找出所有的根对象,标志其为”垃圾”,这个是通过将同步块索引的一位设为0来完成的,我们称这个阶段为”标记”阶段。

           在运行到step3后,obj1和obj2和obj3就是这里的3个根,其中根obj2在堆栈中已经被pop出去了,因此堆栈中只有两个根对象obj1和obj3,如图所示:

            

           因为根obj1均引用了object对象1,所以object对象1的同步块索引的一位被置为1,以标记其不是垃圾,然后检查根obj3的对象引用情况,发现它也引用了object对象1,当它刚要标志其同步索引块的一位时,发现object对象1已经被标记了,则不重新标记它。这样就避免了因循环引用而产生死循环。

          需要注意的是,在标记object对象1时,发现它引用了其他的对象(假设为a),那么对象a也对被标记。

          标记过程会持续,依次检查完所有的根。标记完毕后,堆中的对象要么被标记要么未标记,就会形成一个对象可达图,图中可达的对象不是垃圾,不可达的对象被视为垃圾。知道了哪些是垃圾后,下一步就进入了压缩阶段。

    二.压缩阶段

          压缩阶段主要的任务是将幸存的对象压缩成连续的,因为根据应用程序的局部性原理,这样更有利于减少程序集,释放了内存,解决了堆的空间碎片化问题,同时提高了缓存命中率。对于下图而言,我们就是要把acef对象压缩成连续的,其实很简单,我们只需要把c对象挪到a后面,e对象挪到c后面,依此类推,即可使这些内存对象变成连续的。

          

          在完成这一步后,其实两个问题亟待解决,第一个是c内存压缩后,其在堆中的实际位置变化了,根引用c的位置还是原来的,如果听任下去,将会访问旧的内存地址而造成内存损坏。所以,还要将根中引用c的地址减去在压缩中偏移的字节数,这样就能保证每个根引用的还是原来的c,只不过对象在内存中变换了位置。

          第二个亟待解决的问题是,指向下一个对象在堆中的分配位置NewObjPtr指针也要进行偏移字节数的计算,这样才能保证新对象分配的内存与原有的堆内存是连续的。

          下面是垃圾回收后的托管堆:

          

           经过垃圾回收过后,内存不可能泄漏了,因为对象可达图中的不可达对象,都会被回收;其次不可能因为访问不可达对象而造成内存损坏,因为现在只能引用可达的对象,不可达的对象是引用不了的。

    参考文档

     《CLR via C#》(第4版)

  • 相关阅读:
    判断JS数据类型的四种方法
    JavaScript正则表达式精简
    virtio介绍
    DPDK与SRIOV应用场景及性能对比
    KVM和Xen的区别
    理解 JavaScript 闭包
    JS数组常用操作方法总结
    JavaScript中的 NaN 与 isNaN
    如何在Unity中复制多个组件并粘贴到另一个GameObject上
    Unity Umotion 导入动作发生漂移的解决办法
  • 原文地址:https://www.cnblogs.com/gudi/p/6414622.html
Copyright © 2011-2022 走看看