垃圾回收不是在内存满时才进行,而是只要在0代满了就会进行.而第0代没分配256KB就会满一次.
可以使用GCBeep和GCNotification检查内存回收情况.
垃圾回收采用代的概念,而且只有0,1,2三代. 值类型是不被GC进行垃圾回收的,值类型是在栈上, 当某方法返回时, 栈会恢复到该方法调用前的状态, 该方法在栈上分配的值类型的内存自然就释放了, 不必等GC。而引用类型是在堆上分配, 栈上保存着一个地址而已,保存地址的内存像值类型一样被回收了, 当栈释放后, 即使对象已经没有用了, 但堆上分配的内存还在,只能等GC收集时才能真正释放。
1.finalize close dispose Dispose(bool disposing)
Finalize是CLR提供的一个机制, 它保证如果一个类实现了Finalize方法,那么当该类对象被垃圾回收时,垃圾回收器会调用Finalize方法.而该类的开发者就必须在Finalize方法中处理 非托管资源的释放. 但是什么时候会调用Finalize由垃圾回收器决定,该类对象的使用者(客户)无法控制.从而无法及时释放掉宝贵的非托管资源.由于非托管资源是比较宝贵了,所以这样会降低性能.即使类型构造器抛出了异常,finalize方法也会被调用.
Dispose方法是public的,而dispose(bool)是protected.
Dispose(bool disposing)不是CRL提供的一个机制, 而仅仅是一个设计模式(作为一个IDisposable接口的方法),它的目的是让供类对象的使用者(客户)在使用完类对象后,可以及时手动调用非托管资源的释放,无需等到该类对象被垃圾回收那个时间点.这样类的开发者就只需把原先写在Finalize的释放非托管资源的代码,移植到Dispose(bool disposing)中. 而在Finalize中只要简单的调用 "Dispose(false)就可以了.
如果一个类型的finalize方法是从object继承的,那么CLR会忽略finalize方法.
2. SafeHandle
3. FileStream Stream缓冲区
FileStream Stream都有自己的数据缓冲区,当缓冲区满的时候才会进行写入.如果最后缓冲区中存留数据,是不会主动写入的,直到垃圾回收调用finalize.
Stream在调用finalize方法的时候会将缓冲区中的数据写入磁盘,FileStream 则不会进行该操作因为没有实现finalize方法,这就要求使用人员显式的调用dispose方法或者close,否则会造成数据丢失.
4. 手动监视和控制对象的生存期
CLR为每个AppDomain提供了一个GC句柄表.该表允许应用程序监视对象的生存期,或者手动的控制对象的生存期.
为了在表中添加和删除记录项,需要使用GCHandle类型.GCHandle的Alloc方法接收一个对象和GCHandleType类型的标志,标示对象.
Weak标志使你知道在什么时候一个对象呗判定为垃圾,但内存还无法保证回收.
WeakTrackResurrection 标志使你知道在什么时候一个对象的内存已被回收.
// 摘要:
// 表示 System.Runtime.InteropServices.GCHandle 类可以分配的句柄的类型。
[Serializable]
[ComVisible(true)]
public enum GCHandleType
{
// 摘要:
// 此句柄类型用于跟踪对象,但允许回收该对象。当回收某个对象时,System.Runtime.InteropServices.GCHandle 的内容归零。在终结器运行之前,Weak
// 引用归零,因此即使终结器使该对象复活,Weak 引用仍然是归零的。
Weak = 0,
//
// 摘要:
// 该句柄类型类似于 System.Runtime.InteropServices.GCHandleType.Weak,但如果对象在终结过程中复活,此句柄不归零。
WeakTrackResurrection = 1,
//
// 摘要:
// 此句柄类型表示不透明句柄,这意味着无法通过此句柄解析固定对象的地址。可以使用此类型跟踪对象,并防止它被垃圾回收器回收。当非托管客户端持有对托管对象的唯一引用(从垃圾回收器检测不到该引用)时,此枚举成员很有用。
Normal = 2,
//
// 摘要:
// 此句柄类型类似于 System.Runtime.InteropServices.GCHandleType.Normal,但允许使用固定对象的地址。这将防止垃圾回收器移动对象,因此将降低垃圾回收器的效率。使用
// System.Runtime.InteropServices.GCHandle.Free() 方法可尽快释放已分配的句柄。
Pinned = 3,
}
同时C#提供了一个fixed语句,能在代码块中固定对象,而且效率比GCHandle高效的多,这样在GC回收垃圾进行压缩的时候就不会移动变量引用的对象.
WeakReference 是对GCHandle的一个包装,在内部还是调用GCHandle的方法.要比GCHandle更”重”
System.Runtime.CompilerServices.ConditionalWeakTable<Key,Value> 使编译器可以将对象字段动态附加到托管对象。 TKey: 字段所附加到的引用类型。TValue:字段的类型。 此类型必须是引用类型。
5. 对象复活
当对象在进行垃圾回收时,被标记为不可达,在调用Finalize方法之前要进行复活,以调用对象的finalize方法,如果在finalize方法中,重新添加了对本对象的引用,对象即可真正复活.但一般不推荐这样做.
6. GC.AddMemoryPressure和HandleCollector
7. 预测需求大量内存的操作能否成功
使用MemoryFailPoint,允许在开始一个大的算法之前,检查是否有足够的内存.
8.编程控制垃圾回收器
GC.Collector(int,Mode) 指定回收的代和回收模式
GC.WaitForPendingFinilizers,挂起调用线程,直到处理foreachable队列的线程清空该队列(调用每个finilize方法).
GC.GetGeneration(obj) 获取对象目前所在的代