浅谈.NET垃圾回收

最近在做Winform项目优化,项目运行十天,内存就达到3G,真是让人头疼,到现在还没有完全解决,,,下面来说说.NET垃圾回收原理与算法


每个程序都有这样或者那样的资源,如数据库连接、网络连接、文件操作等等。在面向对象的环境里,每一个类型、每一个程序所用的资源都对应着自己的内存空间,要想使用它们必须为相应的类型实例分配一定的内存空间。


.NET创建一个对象使用new关键字,在IL里面使用newobj指令,这个指令为对象分配一定的内存空间,在此期间CLR要做一下操作:

1、计算类型所有字段所需要的字节总数。

2、在前面所需字节总数基础上再加上两个附加成员所需字节数(一个方法表指针和一个SyncBlockIndex),在32位操作系统中,这两个字段各占32位,合起来将为每个对象增加8个字节。64位系统中,每个字段占用64位空间,将为每个对象增加16个字节。

3、CLR检查保留区域(应用程序进程初始化后,CLR将保留一块连续的地址空间,这段空间并不对应物理内存,改地址空间成为托管堆)中的空间是否满足分配新对象所需的字节数,满足则提交物理内存为其分配空间,IL指令newobj返回为其分配的内存地址,(这里面还设计一个NextObjPtr指针操作,指针指向下一个新建对象在托管堆中的地址)。


每一个托管资源的实例都要放在托管堆中,当托管堆中NextObjPtr指针检测到托管资源已经超出托管堆的地址空间范围时,就要执行垃圾回收:

1、CLR托管堆中的资源也有老幼之分,就是代龄,CLR的托管堆只支持三个代龄,当CLR初始化时,它会为这三代选择三个阙值容量,第0代可能是256KB,第1代可能是3MB,第2代可能是10MB,阙值越大相应的垃圾回收的频率就越低,性能就越高。   代龄的分类是根据垃圾回收的次数,比如 刚开始的时候都是0代,当0代的阙值容量达到时,就执行垃圾回收,0代中没有被回收掉的就变成了1代;当1代的阙值容量达到时,1代就执行垃圾回收,1代中没有被回收掉的就成为了2代;(如果0代阙值容量满了时就对0代执行垃圾回收,如果1代满了就对1代执行)。

2、System.GC提供了可以手动干预垃圾回收的方法

void GC.Collect(Int32 Generation)  强制回收制定代龄的垃圾

void GC.Collect()   回收所以代龄的垃圾

Int32 GetGeneration(Object obj)   得到对象所处的代龄


执行垃圾回收时,垃圾回收器要遍历内存中所以的根,如果托管堆中有跟所引用的对象,那么这个对象就是可达的,如果托管堆中的对象没有任何根引用,就是不可达对象,就意味着可以回收。

执行垃圾回收时,垃圾回收器会挂起当前进程,进行垃圾回收,垃圾回收会调用对象的finalize方法(finalize方法只有在垃圾收集执行时才会被调用,它不会在方法退出或者对象超出范围时被调用),调用finalize方法的条件:

1、第0代对象充满时

2、现实调用GC.Collect方法

3、CLR卸载应用程序域

4、CLR被关闭


在finalize方法被调用的时候,我们可以做些操作让对象复苏,这里不做详细说明


先说到这里,可能有些地方说的不对,请给我留言,


推荐一个店铺

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值