CLR的垃圾回收总结

垃圾回收的本质是,跟踪托管堆中被引用的对象,回收没有被引用的对象。

程序的根,CPU寄存器,函数参数,局部变量,静态字段

垃圾回收的2个阶段,第一阶段,标记阶段,根据线程栈上行,找出仍有根的对象进行标记,这个标记clr是在托管堆中对对象的同步索引的位进行标记。没有被标记的对象就是不可达对象,就是垃圾回收的主要处理的对象。

第二个阶段,就是压缩阶段,简单理解,就是消除内存碎片,让内存连续。既然内容移动了,就必须让可达对象进行重指向。这里注意一个问题,就是对大对象不进行内存移动,大对象就是8M-9M之间的对象。

这里再引出一个问题,就是一个32位进程,32位的OS会分配给他多大的地址空间,这个我也在网上找了很久的答案,答案是4G,其中2G留给OS使用,进程只有2G。也可以把它改为3G,就是需要改变C盘下面的root.ini文件的配置,使os再让出1g给进程。那么一个32位的.NET FRAMEWORK进程能有多大的内存空间呢,据查是800m-1200m。

垃圾回收机制还有2个需要理解的地方。一个是基于代的垃圾回收,一个垃圾回收的策略引擎。

基于代的垃圾回收,有这样3个前提假设,新对象的存活时间比较短,老对象的存活时间比较长,回收一部分垃圾比回收整个托管堆要高效。所有垃圾回收是针对代的回收。新分配的对象位于第0代,当第0代(256k)满了的时候,不可达对象的这时就可以回收,可达的对象放入第1代(2m),直到第1代满了的时候,再清理第1代,把可达对象放入第2代(10m)。垃圾回收的策略引擎就是说垃圾回收是可以自己调节的,会对新对象的分配和垃圾回收状况进行跟踪,调节垃圾回收的代的空间大小以改变垃圾回收的频率。

这样,如果在程序中显示调用了GC.Collect(),是可以强制进行一次垃圾回收的,这样做的缺点就是会打乱垃圾回收的节奏。

垃圾回收工作也给非托管资源的释放留了一个口子,Finalize(终结器)方法,这个终结器就是让对象在垃圾回收之前去调用的。这个我们程序员的任务就是显示写出析构方法,IL中就是override了finalze方法,但是这个访问操作符是protected的,我们还是不能显示调用的。这个方法是垃圾回收去调用,这样由于垃圾回收的时间不确定性造成了这个这个方法的调用时间就是不确定了。为了可以让程序员能主动一点的处理非托管资源的释放,才引出了dipose模式。

clr中也谈了一个对象复活的事,就是说在一个垃圾回收中,如果这个对象重写了finalize方法,那么这个对象就会被放到终结列表,当开始一次垃圾回收时,如果判定这个对象不可达了,先不回收这个对象的内存,而是把它放到f-reachable队列中,让它在这次垃圾回收中存活了下来了,有一个专用的高优先级线程专门去调用f-reachable队列中对象的finalize方法,那么这个对象就变成了不可达对象,将在下一次垃圾回收过程中把它的内存进行回收。

clr也谈了弱引用的作用,弱对象就是垃圾回收可以强制的对这种对象回收。

最后谈谈GC的两种模式,一个是工作站模式,一个是服务器模式。工作站模式,就是针对客户端程序来说的。也分为2中方式,一种是支持并发的回收,一种不支持的,如果没有指定GC的工作模式,那么默认是工作站的并发模式。并发的含义就是多线程,有一个专用的后台线程去进行标记工作,去减少GC工作的第一个阶段的工作。但是这样做效率不一定会高,要考虑到后台这个线程是普通优先级的,会和客户端的线程争用CPU资源。服务器模式使用的就是并发垃圾回收的一种方式,如果是多处理器的机器可以使用这种方式回收。由于我对这块没有深入的体会,只能简单理解来看,以后应该多在具体的项目去试试这个模式。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值