zoukankan      html  css  js  c++  java
  • 什么是应用程序根

    简单来说,一个根是一个引用,这个引用指向堆上面的一个对象的。严格来说,一个根可以有以下几种情况:

       (1) 指向全局对象的引用(尽管C#不支持,但CIL代码允许分配全局对象)

      (2) 指向任何静态对象

      (3) 指向一个应用程序代码中的局部对象

      (4) 指向传入到一个函数中的对象参数

      (5) 指向等待被终结(finalized)的对象

      (6) 任何一个指向对象的CPU寄存器

    在一次垃圾回收的过程中,运行环境会检查托管堆上面的对象是否仍然是从应用程序根可到达的。为了检查可达,CLR会建立一个代表堆上每个可达对象的图。对象图用来记录所有可达的对象。同时,注意垃圾回收器绝不会在图上标记一个对象两次,因此避免了烦人的循环引用。

      假设托管堆上有名字为A,B,C,D,E,F和G的对象集合。在一次垃圾回收过程中,会检查这些对象(同时包括这些对象可能包含的内部对象引用)是否是根可达的。一旦图被建立起来,不可达的对象(在此是对象C和F)被标记为垃圾。

      下图是上述场景的一个可能的对象图(你可以把箭头读作依赖或者需要,例如"E依赖于G,间接依赖于B,“A不依赖任何对象”等)。

    (创建的对象图是用来决定哪些对象是应用程序根可达的。)

      一旦一个对象已经被标记为终结(此例子中是C和F--在图中没有他俩),它在内存中就被清理掉了。在此时,堆上的剩余内存空间被压缩,这会导致CLR修改活动的应用程序根集合(和对应的指针)来指向正确的内存位置(这个操作是自动透明的)。最后,调整下一个对象指针来指向下一个可用的内存位置。

      下图阐明了清除和压缩堆的过程。

    到这里,通过对应用程序根的作用的理解,我们知道了如何知道一个对象是“不再需要”的。通俗点来说就是,这个对象在应用程序中已经无需被访问了,成为了一座“孤岛”,自然也就不再需要它了。

    摘抄:https://www.cnblogs.com/MaMaNongNong/p/11945161.html

    标题:谈谈.net对象生命周期

    理解对象的代 — 垃圾回收过程的优化

      在尝试找到不可达的对象时,CLR并不是检查托管堆上的每个对象。很明显,这样做会消耗大量时间,尤其在大型(例如现实中)程序中。

      为了帮助优化这个过程,堆上的每个对象被分配到一个特殊的"代”。代这个概念背后的想法很简单:对象在堆上存活的时间越长,接下来它继续存在的可能性也就越大,即较旧的对象生存期长,较新的对象生存期短。例如,实现Main()的对象一直在内存中,直到程序结束。相反,最近才被放到堆中的对象(例如在一个函数范围里分配的对象)很可能很快就不可达。

      在堆上的每个对象属于以下的某一个代:

        Generation 0: 标识一个最近分配的还没有被标记为回收的对象

      Generation 1: 标识一个经历了一次垃圾回收而存活下来的对象(例如,他被标记为回收,但由于堆空间够用而没有被清除掉)

      Generation 2:标识一个经历了不止一轮垃圾回收而存活下来的对象。

      垃圾回收器首先会检查generation 0的所有对象。如果标记并清理这些对象(译者注:因为新对象的生存期往往较短,并且期望在执行回收时,应用程序不再使用第 0 级托管堆中的许多对象)后产生了足够使用的内存空间,任何存活下来的对象就被提升到Generation 1。为了理解一个对象的代如何影响回收的过程,可以查看下图。下图解释了generation 0中一次垃圾回收后,存活的对象被提升的过程。  

    (generation 0 中的存活对象被提升到generation 1)

      如果所有的generation 0对象都被检查了,但是产生的内存空间仍然不够用,就检查一遍generation 1中的所有对象的可达性并回收。存活下来的generation 1对象被提升到generation 2。如果垃圾回收器仍然需要额外的内存,generation 2的对象就经历检查并被回收。此时,如果一个generation 2的对象存活下来,它仍然是一个generation 2的对象。

      其实通过对象的代的设计是想达到这么一个效果:新对象(比如局部变量)会被很快回收,而老一些的对象(如一个应用程序对象)不会被经常骚扰

      说到底,对象代的设计就是为了优化垃圾回收的过程。  

    构建可终结对象 — 非托管资源处理第一式

      以一名c#开发者的直觉告诉你,大多数的c#类都不需要显式的清理逻辑。原因很简单:如果类型使用了其他托管对象,一切都最终会被垃圾回收。

      问:那在什么时候需要显式地清理呢

      答案是:在你使用非托管资源时(例如原始的操作系统文件句柄、原始的非托管数据连接或其他非托管资源),才可能需要设计一个在用完后清理自身垃圾的类

      比如说下面这个类:

    //数据库上下文类
       public class SqlDbContext
       {
           //...(其他被引用的对象实例)
    
           //类中包含的非托管资源(需要调用 Dispose()函数进行资源的释放)
           SqlConnection sqlConnection = new SqlConnection("...");  
                
       }
  • 相关阅读:
    Perl 杂记
    Block abstraction view(Create & Reference)
    sed & awk
    multi-voltage design apr
    APR Recipe
    IN2REG group 的时序分析
    关于 clock tree
    ICC Stage Flow
    ocv & derate & crpr
    clock gating check
  • 原文地址:https://www.cnblogs.com/Tpf386/p/12009311.html
Copyright © 2011-2022 走看看