• 第二十一章 垃圾回收


    垃圾回收不是在内存满时才进行,而是只要在0代满了就会进行.而第0代没分配256KB就会满一次.

    可以使用GCBeep和GCNotification检查内存回收情况.

    垃圾回收采用代的概念,而且只有0,1,2三代. 值类型是不被GC进行垃圾回收的,值类型是在栈上, 当某方法返回时, 栈会恢复到该方法调用前的状态, 该方法在栈上分配的值类型的内存自然就释放了, 不必等GC。而引用类型是在堆上分配, 栈上保存着一个地址而已,保存地址的内存像值类型一样被回收了, 当栈释放后, 即使对象已经没有用了, 但堆上分配的内存还在,只能等GC收集时才能真正释放。

    1.finalize  close dispose Dispose(bool disposing)

    close和dispose是一样的效果.

    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) 获取对象目前所在的代

  • 相关阅读:
    当再多大公司慢慢的放弃微软的技术时, 不知大家怎想?
    【叶子函数分享五十四】汉字转拼音函数 [转]
    java_easyui体系之DataGrid(4)[转]
    java_easyui体系之DataGrid(3)[转]
    java_easyui体系之DataGrid(2)[转]
    java_easyui体系之DataGrid(1)[转]
    java_easyui体系之目录 [转]
    Java 并发和多线程(三) 多线程的代价 [转]
    Java 并发和多线程(二) 多线程的优点 [转]
    Java 并发和多线程(一) Java并发性和多线程介绍[转]
  • 原文地址:https://www.cnblogs.com/zhangliming/p/3491739.html
Copyright © 2020-2023  润新知