专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > CLR

渣滓回收期算法简介

发布时间:2011-06-23 13:51:21 文章来源:www.iduyao.cn 采编人员:星星草
垃圾回收期算法简介

垃圾回收器检查托管堆中是否有应用程序不再使用的对象,如果有,他们使用的内存就可以回收(如果一次垃圾回收之后堆中仍然没有可用的内存,new操作符就会抛出一个OutOfMemoryException)。垃圾回收器如何知道应用程序正在使用一个对象呢?这个说起来比较复杂。

每个应用程序都包含一组根。每个根都是一个存储位置,其中包含指向引用类型对象的一个指针。该指针要么引用托管堆中的对象,要么为null,例如:类型中定义的任何静态字段被认为是一个根。除此之外,任何方法的参数和局部变量也被认为是一个根。只有引用类型的变量才能被认为成根;值类型的变量永远不被认为成根。

垃圾回收期开始执行时,它假设堆中所有对象都是垃圾,换句话说,它假设线程栈中没有引用堆中对象的变量,没有CPU寄存器引用堆中的对象,也没有静态字段引用堆中的对象。垃圾回收期第一阶段就是所谓的Marking(标记)阶段。垃圾回收期沿着线程栈上行检查所有根。如果发现一个根引用一个对象,就在对象的“同步块索引字段”上做一个标记。例如:垃圾回收器发现一个局部变量指向堆中的一个对象。下图展示了一个堆,其中包含几个已经分配的对象。应用程序的根直接引用对象A、C、D、F。

所有这些对象都以标记。标记对象D时垃圾回收期发现这个对象含有一个引用了对象H的字段,造成对象H也被标记。垃圾回收期就是这样,以递归的形式遍历所有可达的对象。

 

标记好根和他引用的字段之后,垃圾回收器检查下一个根,并继续标记对象。如果垃圾回收期试图标记一个先前标记过的对象。就会停止沿着这个路径走下去,这个行为有两个目的。首先垃圾回收期不会多遍历一组对象,所以性能能得到提升。其次,如果存在对象的循环链表,可以避免陷入无限循环。

检查好所有根之后,堆中将包含一组已标记的对象和未标记的对象。已标记的对象是通过应用程序可达的对象,而未标记的对象时不可达的,不可达的对象被认为是垃圾,他们占据的内存就可以回收,现在垃圾回收期开始第二个阶段压缩阶段。这个阶段垃圾回收器线性的遍历堆,以寻求未标记对象的连续内存块。如果发现的内存块比较小,垃圾回收期会忽略他们,如果发现的内存块比较大,垃圾回收器就会把非垃圾的对象移动到这里以压缩栈。

 

很自然,移动内存中的对象之后,包含指向这些对象中的指针变量将变的无效。所以垃圾回收期现在开始重现访问应用程序的根,并修改他们来指向新内存的地址。另外,如果对象中的字段指向的是另一个已移动的对象的字段,垃圾回收期也要负责修正这些字段的值。堆内存压缩之后,托管堆得NextObjPtr指针指向紧接在最后一个非垃圾回收之后的位置 ,下图是垃圾回收之后的托管堆。

 

 

如你所见,垃圾回收期造成显著的性能损失,这是使用托管堆得主要缺点。但是需要注意的是,垃圾回收期只有在0代已满的时候才回收。在此之前,托管堆得性能远远高于C运行时。最后,CLR的垃圾回收期提供了一些特殊的优化措施,可以大幅提高垃圾回收的性能。(后面讲说代的概念)

作为程序员,我们从前面的讨论中得出两个重要的认识。第一点,不必自己写代码来管理应用程序所用的对象的生存期。第二点,前面一章描素的bug将不复存在。首先,不可能再发生对象泄露的情况。因为任何对象只要应用程序没有根引用它,都会在某个时刻被垃圾回收期回收,所以应用程序不可能发生内存泄露的情况,另外应用程序也不可能再访问已经释放的对象。其次,不可能访问一个已经释放的对象。这是因为如果对象可达,就不会被释放;如果它不可达,应用程序就没办法访问它。另外,由于垃圾回收器导致了内存的压缩,所以托管对象不可能造成托管堆进程虚拟空间地址的碎片化。如果是非托管代码,地址空间的碎片化可能非常严重。但是使用托管堆是这个问题就不发生了,另外是在使用大对象的时候,托管堆仍然有可能碎片化。

友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

  • [精粹]正则表达式30分钟入门教程(转)

    [精华]正则表达式30分钟入门教程(转) 前言   今天做东西的时候碰到个正则表达式的需求,以前做数据验证的时候因为都是一些通用的东...

  • WCF学习1

    WCF学习一 在阅读博客园 WCF开发实战系列一:创建第一个WCF服务 一文中,发现手动配置App.config还是有难度。这篇文章没讲很多...

  • .NET 类库研究必备参照 添加微软企业库源码

    .NET 类库研究必备参考 添加微软企业库源码 前不久,为大家提供了一个.NET 类库参考源码的网站,扣丁格鲁(谐音“coding guru...

  • .NET 类库研究必备参照 扣丁格鲁

    .NET 类库研究必备参考 扣丁格鲁 .NET 类库的强大让我们很轻松的解决常见问题,作为一个好专研的程序员,为了更上一层楼,研究CLR...

  • 垃圾回收机制GC知识再总结兼谈怎么用好GC

    垃圾回收机制GC知识再总结兼谈如何用好GC 一、为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1、为对应的资源分配内...

  • .NET 4.5.1 参照源码索引

    .NET 4.5.1 参考源码索引...

  • 关于GC跟析构函数的一个趣题

    关于GC和析构函数的一个趣题 这个有趣的问题感谢装配脑袋友情提供。 请看如下代码: public class Dummy { publi...

  • 对程序集的几点懂得

    对程序集的几点理解   CLR对程序集的解释是:程序集是一个或多个类型定义文件及资源文件的集合。平时我们常见的后缀为dll或exe的...

  • 渣滓回收期算法简介

    垃圾回收期算法简介 垃圾回收器检查托管堆中是否有应用程序不再使用的对象,如果有,他们使用的内存就可以回收(如果一次垃圾回收之后...

  • CLR值类型跟引用类型

    CLR值类型和引用类型 知识点:引用类型、值类型、装箱、拆箱 CLR支持两种类型:引用类型和值类型。引用类型在堆上分配内存,值类型在线...