.net内存释放(托管堆与非托管堆的释放)

托管堆:

1、垃圾回收器

    .net的运行库采用的是垃圾回收器来回收的方式。垃圾回收器本身也是一个程序。程序动态请求的内存都分配到堆上,在.net中,CLR维护它自己的托管堆供.net程序使用。

      每隔一段时间.net就会检查托管堆,当检查到需要清理堆时,.net就调用垃圾回收器这个程序。垃圾回收器会扫描堆上的对象的引用,不再有引用的对象就被删除。

      垃圾回收器调用的时间是不确定的,除非代码中有调用垃圾回收器(System.GC.Collect()).


2、内存碎片的处理

     由于堆的释放时刻是由堆上对象的生存周期决定的,这就决定了堆的释放顺序是不定的,必然产生内存碎片。就像操作系统的磁盘分配机制一样,若需要给一个新的对象分配空间,CLR需要搜索堆,直到找到足够大的空间来存储新对象。实际上垃圾回收器会避免堆出现碎片的现象。

     回收器在一次释放动作结束后会将堆上剩余的对象往堆顶移动,回收器会更新被移动对象新的存储地址。这就又形成了整块的未分配的空间。

     虽然移动对象并更新地址会消耗一定的性能,但是由于分配速度和访问速度会快很多,足以弥补此消耗。

     :垃圾回收器并不保证每次回收动作都能将所有未被引用的对象删除。


3、提高回收性能的机制

     a、分代机制:所有新创建的对象会放在第0代堆上,直到回收器进行了一次清理动作后仍存在的对象会被移动到另一片连续的地址空间中,即第1代堆上。而之前第1代上剩余的对象会被移动到第2代堆上,此时第0代堆空闲,等待新创建的对象。每一次回收动作都重复此过程。新的对象被回收的几率更大,将这些对象分阶段存放,回收过程速度加快。

    :在创建新对象时,如果所需空间超出了第0代对应的空闲区域,回收器会进行垃圾回收,将第0代区域空闲出来。

     b、大对象堆:当对象所需区域大于85000个字节时,对象会被放在大对象堆上。大对象堆是独立于一般堆的存储区域,大对象堆是不进行移动以达到获得连续的空闲区域,因为挪动大对象代价很大。


    C、线程回收机制:第2代堆上的对象是生命周期较长的对象,第2代对象堆和大对象堆是通过线程来回收的。所以只有回收第0、1代堆对象时应该程序才会阻塞执行。在大型的服务器程序中此功能优势明显。将配置文件元素<gcConcurrent>设为false,此功能关闭

    d、控制垃圾回收方式。GCSettings.LatencyMode属性。此方式还有待理解



二、非托管堆

       回收器不知道如何释放非托管资源,如文件句柄,网络连接、数据库连接等。当非托管对象被托管对象引用时,托管对象被释放时应确保其相关的非托管对象被释放。

       以下两种方法可解决释放非托管资源的问题:

       1、在定义类时,声明一个析构函数

    

     在delphi中,我习惯在析构函数中做一些最后的清理工作,以确保对象释放前将其类中用到的成员对象释放。但是

.net因为有垃圾回收器,且回收的时间是不定的,可能出现在调用析构函数的时候,对象已经被回收了。

所以只靠析构函数来达到此目的是不行的。通过析构函数和下面将要提到的IDisposable接口联合适用是可以的。


   2、在类中实现System.IDisposable接口

         class  MyClass:IDisposable

            {

                 public void Dispose()

                  {

                      //释放非托管资源

                  } 

            }

     两种调用方式:

       a、 using关键字方式,对象声明周期结束时会自动调用Dispose函数。此using与命名空间无关

            using(MyClass classA= new MyClass())

            {

             //do something

             }//对象的生命周期结束

     b、主动调用

          try

             {  

                 MyClass classA= new MyClass();

                 //do something

             }

         finally

           {

              Dispose();//显示调用

           }

           

 


        

            


  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值