.NET垃圾回收
托管堆的工作方式非常类似于栈,在某种程度上,对象会在内存中一个挨一个的放置,这样就很容易使用指向下一个空闲存储单元的堆指针,来确定下一个对象的位置。在堆上添加更多的对象时,也容易调整。但这比较复杂,因为基于堆的对象的生存期与引用它们的基于栈的变量的作用域不匹配。
在垃圾回收器运行时,它会从堆中删除不再引用的所有对象。在完成删除操作后 ,堆会立即把对象分散开来,与已经释放的内存混合在一起。如果托管的堆上也是这样,在其上给新对象分配内存就成为一个很难处理的过程,运行库必须搜索整个堆,才能找到足够大的内存块来存储每个新对象。但是,垃圾回收器不会让堆处于这种状态。只要它释放了释放的所有对象,就会把其他对象 移动回堆的端部,再次形成一个连续的内存块。因此堆可以继续像栈那样确定在什么地方存储新对象。当然,在移动对象时,这些对象的所有引用都需要用正确的新地址来更新,但垃圾垃圾回收器也会处理更新问题。
垃圾回收器这个压缩操作是托管的堆与非托管的旧堆的区别所在。所用托管的堆,就只需要读取堆指针的值即可,而不需要遍历地址的链表,来查找一个地方来放置新数据。因此,在.NET实例化对象要快得多。有趣的是,访问它们也比较快,因为对象会压缩到堆上相同的内存区域,这样需要交换的页面较少,Microsoft相信,警官垃圾回收器需要做一些工作,压缩堆,修改他移动的所遇对象引用,致使性能降低,但这些性能会得到更多弥补。
垃圾回收器运行时,它实际上会降低应用程序的性能,因为在垃圾回收器完成任务之前,应用程序不可能继续运行。使用.NET垃圾回收器可以减小这个问题的影响,因为它是一个世代(generational)垃圾回收器。
创建对象时,会把这些对象放在托管堆上。堆的第一部分成为第0代。创建新对象时,会把它们移动到堆的这个部分中。因此,这里驻留了最新的对象。对象会继续放在这个部分,直到第一个对象集合在垃圾回收过程中生成。这个清理过程之后仍然保留的对象会被压缩,然后移动到堆的下一部分或世纪部分----第一代对应的部分。
此时,第0代对应的部分为空,所有的新对象都再次放在这一部分上。在垃圾回收过程中遗留下来的旧对象放在第一代对应的部分上。老对象的这种移动会再次发生。接着重复下一次回收过程。这意味着,第1代中在垃圾回收过程中遗留下来的对象会移动到堆的第2代,位于第0代的对象会移动到第1代,第0代人用于放置新对象。
释放非托管的资源
垃圾回收器的出现意味着,通常不需要担心不再担心对象,只要让这些对象的所有引用都超出作用域,并允许垃圾回收器在需要时释放内存即可。但垃圾回收器不知道如何释放非托管的资源(例如文件句柄、网络链接、数据库连接)

浙公网安备 33010602011771号