clr via C#笔记(6)

垃圾回收算法

垃圾回收器假设堆中所有对象都是垃圾。垃圾回收器的第一个阶段是所谓的标记阶段,在这个阶段,垃圾回收器沿着线程栈上行以检查所有根。如果发现一个根引用了一个对象,就在对象的同步块索引字段上开启一位------对象就是这样标记的。已标记的对象是通过应用程序的代码可达的对象,未标记的对象是不可达的,被认为是垃圾。现在垃圾回收器开始第二个阶段,即压缩阶段。在这个阶段垃圾回收器线性地遍历堆,以寻找未标记对象的连续内存块。如果发现内存块较小,垃圾回收器会忽略它们。但是,如果发现大的、连续的可用的内存块,垃圾回收器会把非垃圾的对象移动到这里以压缩堆。压缩后,包含指向这些对象的指针的变量和cpu寄存器现在都会变得无效。所以,垃圾回收器必须重新访问应用程序的所有根,并修改它们来指向对象的新内存位置。

对象的生存期不一定与方法的生存期相同,只要对象变得不可达就有可能被垃圾回收

使用终结操作符来释放本地资源

CriticalFinalizerObject  http://www.360doc.com/content/12/0220/18/6075898_188128762.shtml

clr不保证各个Finalize方法的调用顺序,因此在写一个Finalize方法时,应避免访问定义了Finalize方法的其他类型的对象

如果对象的类型定义了Finalize方法,那么在该类型的实例构造器被调用之前,会将指向该对象的一个指针放到一个终结列表中。终结列表是由垃圾回收器控制的一个内部数据结构。列表中的每一项都指向一个对象,在回收该对象的内存之前,应该调用它的Finalize方法。

所有定义了finalize方法的类型都应同时实现DisPose模式,使类型的用户对资源的生存期有更多的控制。但是,类型也可实现Dispose模式,但不定义Finalize方法。如System.IO.BinaryWriter

Dispose模式

一个有趣的依赖性问题

手动监视和控制对象的生存期

有时本地资源会消耗大量内存,但用于包装该资源的托管对象只占用了非常少的内存,如果进程操作多个比较大的资源,内存消耗将快速增长,可以使用GC类的AddMemoryPressure和RemovememoryPressure方法。

 大对象

任何85000字节或更大的对象都被自动视为大对象。大对象从一个特殊的大对象堆中分配,大对象从不压缩,因为在堆中下移85000字节的内存会浪费大量cpu时间。但是,写代码时永远都不要假设大对象是不移动的。大对象总是被认为是第2代的一部分,所以只能为需要长时间存活的资源创建大对象。如果分配短时间存活的大对象,将导致第2代被频繁的回收,这会损害性能

猜你喜欢

转载自blog.csdn.net/zhangwenjie1105/article/details/18303999