GC工作原理
在.Net2.0中GC是怎样清理托管堆的?

解决方案 »

  1.   

    .NET Framework 的垃圾回收器管理应用程序的内存分配和释放。每次您使用 new 运算符创建对象时,运行库都从托管堆为该对象分配内存。只要托管堆中有地址空间可用,运行库就会继续为新对象分配空间。但是,内存不是无限大的。最终,垃圾回收器必须执行回收以释放一些内存。垃圾回收器优化引擎根据正在进行的分配情况确定执行回收的最佳时间。当垃圾回收器执行回收时,它检查托管堆中不再被应用程序使用的对象并执行必要的操作来回收它们占用的内存。在 .NET Framework 1.0 版中,公共语言运行库 (CLR) 具有一个用于大型对象堆的独立内存管理器。在某些情况下,该内存管理器不将未使用的内存返回给操作系统,在少数情况下,它还会使该内存不能垃圾回收。这样会由于虚拟地址空间碎片而导致内存分配失败。在 .NET Framework 1.1 和 2.0 版中,大型对象堆由称为堆片段的连续内存区域组成,这些区域完全对齐以使虚拟内存碎片减到最少。在垃圾回收过程中,从大型对象中回收的空间被合并起来并置于自由列表中。只包含自由列表项的堆片段被释放,内存被返回给操作系统。对大型对象堆所做的这些更改有效消除了由这种形式的虚拟地址空间碎片导致的内存分配故障。GC类中的方法影响何时对对象进行垃圾回收以及何时释放对象所分配的资源。此类中的属性提供以下信息:系统可用内存总量、分配给对象的内存的周期类别(代)。垃圾回收器跟踪并回收托管内存中分配的对象。垃圾回收器定期执行垃圾回收以回收分配给没有有效引用的对象的内存。当使用可用内存不能满足内存请求时,垃圾回收会自动进行。或者,应用程序可以使用 Collect 方法强制进行垃圾回收。垃圾回收由以下步骤组成: 垃圾回收器搜索托管代码中引用的托管对象。垃圾回收器尝试完成没有被引用的对象。垃圾回收器释放没有被引用的对象并回收它们的内存。在回收期间,如果垃圾回收器在托管代码中找到对某对象的一个或多个引用,则不会释放该对象。然而,垃圾回收器不识别非托管代码中对对象的引用,因此,除非明确禁止,否则它有可能释放非托管代码中以独占方式使用的对象。KeepAlive 方法提供一种机制,该机制可防止垃圾回收器回收在非托管代码中仍使用的对象。除托管内存分配外,垃圾回收器的实现不维护有关一个对象所保持的资源(如文件句柄或数据库连接)的信息。当某个类型使用的非托管资源在回收该类型的实例之前必须释放时,该类型可以实现终结器。多数情况下,终结器通过重写 Object..::.Finalize 方法来实现,但是,用 C# 或 C++ 编写的类型实现析构函数,由编译器将析构函数转换为对 Object..::.Finalize 的重写。多数情况下,如果某对象有终结器,则垃圾回收器会在释放该对象前调用其终结器。不过,垃圾回收器并不是在所有情况下都需要调用终结器;例如,当 SuppressFinalize 方法显式禁止调用终结器时,垃圾回收器就不需要调用终结器。此外,不需要垃圾回收器使用特定线程来完成对象,也不需要垃圾回收器为相互引用、但能以其他方式用于垃圾回收的对象保证终结器的调用顺序。在资源必须在特定时间释放的方案中,类可以实现 IDisposable 接口,该接口包含执行资源管理和清理任务的 IDisposable..::.Dispose 方法。实现 Dispose 的类作为它们的类协定的一部分,必须指定类使用者是否需要及在什么时候调用该方法来清理对象。默认情况下,垃圾回收器并不调用 Dispose 方法,然而 Dispose 方法的实现可以调用 GC 类中的方法来自定义垃圾回收器的完成行为。建议垃圾回收器使用代来支持对象老化,但这不是必需的。代是对象在内存中相对存现时期的度量单位。对象的代数或存在时期指示对象所属的代。较近创建的对象属于较新的代,比在应用程序生命周期中较早创建的对象的代数低。最近代中的对象位于零代中。给实现者的说明:垃圾回收器的此实现支持三代对象。使用 MaxGeneration 确定系统所支持的最大代数。对象老化允许应用程序针对一组特定的代进行垃圾回收,而不需要垃圾回收器计算所有代。
      

  2.   

    这里有篇文章,讲得很好!http://www.cppblog.com/mzty/archive/2006/04/30/6486.html
      

  3.   

    不过我听别人说在.net 2.0中把内寸分为了4个袋。0,1,2,3袋
    所有对象最早寸放在0中,垃圾回收处理3次后,如果对象还是有价值的。将被放入1袋中。依次类推。
    最高的袋处理垃圾时间的间隔比底一级的袋都长些。
    也就是说0袋如果每1分钟处理一次,那么1可能3分钟处理一次...
    这种说发正确吗?
      

  4.   

    .Net中的垃圾回收器中目前有三个生存期等级:0,1和2。0、1、2等级对应的托管堆的初始化大小分别是256K,2M和10M。当0等级堆超过256K后,GC会检查是否可以回收.如果有要销毁的对象,就找出来并进行销毁,然后把不用回收的对象转移到1等级托管堆中.此时0等级托管堆应该是空的.当有新的对象被创建时,又会在0等级托管堆中创建.直到1等级托管堆满了后,会将1等级托管堆的未被销毁的对象转移到2等级托管堆中.以此进行着.当然,各等级的托管推大小不是不变的.GC有个机制,发现改变大小能够提高性能的话,会改变托管堆的大小。