作者:cornfield
漫谈.Net中的自动垃圾收集(Garbage Collection)机制
一直以来,垃圾收集(Garbage Collection)在软件界的名声并不好。很多程序员认为垃圾收集做得不如自己来的直接,高效。这种说法有些时候是对的,一个精心为自己的特定程序设计定制的内存回收方法,肯定比为所有程序提供垃圾回收性能要高。但那对程序员要求甚高,一个项目下来花在内存回收的设计上的时间和精力是很可观的,而稍有不慎便会酿成灾难性的错误,技术再高超的程序员负担不起,整个现代软件工业也负担不起。把这样普遍而又繁重的任务交给系统处理,将程序员从中解脱出来专注于事务逻辑和系统功能的实现,已经成为软件业的共识。微软新推出的.Net平台架构便引入了自动垃圾回收机制,本文将详细解剖其中的原理,回答诸如垃圾回收怎样工作?怎样控制垃圾回收?什么时候需要控制垃圾回收?什么又是垃圾回收不能解决的?等等重要问题,为.Net平台下的系统开发人员提供设计时的参考。
要搞清楚.Net 运行时的垃圾回收机制,首先需要搞清楚.Net运行时内存分配的情况。.Net 运行时对受管资源(Managed Resource)采用对象引用的堆式分配(Heap Allocation)方法。这种分配方法大多数时候是非常快的。一个实际系统的内存总是有限的,当系统的剩余的可分配的内存资源不多时,.Net 运行时便会“预见”到下面的内存资源将可能不会满足下面的内存分配请求,于是它便会开始执行垃圾回收释放那些系统不再引用的内存资源。.Net垃圾回收器采用的是一种叫做“标志紧缩”(Mark and Compat)的算法。每当垃圾收集开始,.Net垃圾收集器从运行时目前的根对象(包括全局对象,本地对象,静态对象,CPU寄存器对象),开始寻找那些被根对象引用的所有对象,这些对象便是在垃圾收集时运行时正在应用的对象,除去这些,其他的受管运行时对象(Managed Runtime Object)便是系统不再使用的对象,于是便可以进行垃圾收集。所有引用的对象被向下拷贝到运行时受管堆(Runtime Managed Heap),同时修改它们的引用指针。需要指出的是,在.Net垃圾收集器移动引用对象和改变引用指针时,系统不能在这些对象上有任何操作,这一点由运行时的互斥机制来保证,无需程序员干涉。
遍历目前所有被引对象的耗费往往是巨大的,实际上也不必这样做。一个经验的认识是,当一个对象在内存中驻留的时间越长,那么它越有可能继续被引用留在内存中。相反,一个对象在内存中驻留时间越短,它越有可能被收集。.Net收集器采用一种称作“代分”(Generation Division)的方法来体现这种经验的内存驻留理论。它把受管堆中的对象分成三代(Generations). 第一代是没有经历过垃圾收集驻留在内存中的对象,他们通常是一些局部变量,它们的生命最短。第二代是仅经历过一次垃圾收集仍然驻留在内存中的对象,它们通常是一些如表单,列表,按钮等生命较短的对象。第三代是经历过两次及两次以上的垃圾收集后仍然驻留在内存中的对象,它们通常是一些应用程序对象,它们往往要在内存中驻留很长时间。当运行时收集器开始执行垃圾收集时,它首先对第一代对象进行垃圾收集,这通常会释放较大的内存空间,往往会满足下面的内存请求。如果这一代的收集结果不理想,那么便会对第二代读像进行收集,同样如果还不理想,便进行第三代的垃圾收集。
.Net垃圾回收机制支持一种称作终止化(Finalizaion)的概念。这有点类似C++中的析构函数。终止化操作在垃圾收集执行后进行一些非受管资源的清除工作,它在.Net运行时里有很多限制,往往不被推荐实现。当程序员对一个对象实现了终止器(Finalizer)后,运行时便会将这个对象的引用加入一个称作终止化对象引用集的链表,作为要求终止化的标志。当垃圾收集开始时,若一个对象不再被引用但它被加入了终止化对象引用集的链表,那么运行时将此对象标志为要求终止化操作对象。待垃圾收集完成后,终止化线程便会被运行时唤醒执行终止化操作。显然这之后要从终止化对象引用集的链表中将之删去。容易看出来,终止化操作会给系统带来额外的开销。终止化是通过启用线程机制来实现的,这有一个线程安全的问题。.Net运行时不能保证终止化执行的顺序,也就是说如果对象A有一个指向对象B的引用,两个对象都有终止化操作,但对象A在终止化操作时并不一定有有效的对象A引用。所以.Net运行时不推荐对对象进行终止化操作,只是在有非受管资源如数据库的连接,文件的打开等需要严格释放时,才应用终止化操作。
大多数时候,垃圾收集应该交由.Net运行时来控制,但有些时候,可能需要人为地控制一下垃圾回收操作。例如在操作了一次大规模的对象集合后,我们确信不再在这些对象上进行任何的操作了,那我们可以强制垃圾回收立即执行,这通过调用System.GC.Collect() 方法即可实现,但频繁的收集会显著地降低系统的性能。还有一种情况,已经将一个对象放到了终止化对象引用集的链上了,但如果我们在程序中某些地方已经做了终止化的操作,在那之后便可以通过调用System.GC.SupressFinalize()来将对象的引用从终止化对象引用集链上摘掉,以忽略终止化操作。始终应该清楚的是,终止化操作的系统负担是很重的。
综上所述,.Net垃圾回收机制负责回收系统不再使用的受管内存资源,它通过一定的优化算法来选择收集的对象和时间。程序员只有在释放大量受管资源时可以进行立即强制垃圾收集,在释放非受管资源时采用终止化操作来处理,其它时间将资源的回收交由.Net垃圾收集起来做。
希望广大网友多多跟帖讨论!
漫谈.Net中的自动垃圾收集(Garbage Collection)机制(转)
时间: 2024-12-08 22:21:27
漫谈.Net中的自动垃圾收集(Garbage Collection)机制(转)的相关文章
浅谈PHP5中垃圾回收算法(Garbage Collection)的演化
前言:PHP是一门托管型语言,在PHP编程中程序员不需要手工处理内存资源的分配与释放(使用C编写PHP或Zend扩展除外),这就意味着PHP本身实现了垃圾回收机制(Garbage Collection).现在如果去PHP官方网站(php.net)可以看到,目前PHP5的两个分支版本PHP5.2和PHP5.3是分别更新的,这是因为许多项目仍然使用5.2版本的PHP,而5.3版本对5.2并不是完全兼容.PHP5.3在PHP5.2的基础上做了诸多改进,其中垃圾回收算法就属于一个比较大的改变.本文将分别
细述 Java垃圾回收机制→Java Garbage Collection Monitoring and Analysis
Java垃圾回收监控和分析工具 Java VisualVM Naarad GCViewer IBM Pattern Modeling and Analysis Tool for Java Garbage Collector HPjmeter IBM Monitoring and Diagnostic Tools for Java – Garbage Collection and Memory Visualizer Verbose GC Analyzer Java VisualVM Java Vi
细述 Java垃圾回收机制→How Java Garbage Collection Works?
这是垃圾回收机制系列文章的第二篇.希望您已经读过了第一部分Java垃圾回收简介. Java垃圾回收是一个自动运行的管理程序运行时使用的内存的进程.通过GC的自动执行JVM将程序员从申请和释放内存的繁重操作中解放出来. Java垃圾回收GC初始化 作为一个自动执行的进程,程序员不需要在代码中主动初始化GC.Java提供了System.gc()和Runtime.gc()这两个hook来请求JVM调用GC进程. 尽管要求系统机制给程序员提供调用GC的机会,但是实际上这是由JVM负责决定的.JVM可以选
自动垃圾收集怎么知道我的内存还用不用?
问题描述 自动垃圾收集怎么知道我的内存还用不用?被他删了,我又突然要用怎么办?他判断为垃圾的原则是什么?msdn中也没有说清楚啊 解决方案 解决方案二:那你程序终止了嘛那就会自动垃圾收集了啊!呵呵,随便说说的!解决方案三:一般来说对象出了它的作用域之后GC就会自动将其释放掉了吧解决方案四:自动垃圾收集怎么知道我的内存还用不用?被他删了,我又突然要用怎么办?他判断为垃圾的原则是什么?msdn中也没有说清楚啊==CLR会检查每一个托管堆中的对象,在栈中是否还有指向它的引用,如果没有,则这个对象可以回
Word2010文档中应用自动套用格式
"自动套用格式"功能可以帮助用户根据"自动套用格式"选项中预设的格式迅速格式化选中的Word文档,用户首先需要将"自动套用格式"按钮放置到Word2010文档窗口的快速访问工具栏(参考教程<将"自动套用格式"命令放在快速访问工具栏>).在Word2010文档中应用自动套用格式的步骤如下所述: 第1步,打开Word2010文档窗口,选中需要应用自动套用格式的文本(如果不选中文本,自动套用格式将作用于整篇Word文
Garbage Collection
3)Garbage Collection State the behavior that is guaranteed by the garbage collection system and write code that explicitly makes objects eligible for collection. 1. Garbage collection is a mechanism for reclaiming memory from objects that are no l
Eclipse中如何自动添加头文件(add include)
在使用Eclipse写程序时, 经常遇到需要找头文件的问题, 在Eclipse中, 包含自动添加头文件的功能; 可以在Java, C++等插件中, 自动添加; 位置: Source -> Add Include (Ctrl+Shift+N): 作者:csdn博客 u012515223 更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/Java/
智能光网络中的自动发现技术
0.前言 智能光网络中存在多种不同的链路资源,如光纤链路.波长链路.SDH中各种STM层链路和VC层链路,以及OTN中的各种OTM层链路和OCh层链路等等. 这些链路在ASON中称为子网点(SNP)链路,为了路由协议的可扩展性和路由分集,多个不同的SNP链路可以组合成子网点池(SNPP)链路(在GMPLS中这些SNP链路称为数据链路,而把这些SNPP链路称为业务量工程(TE)链路).在ASON中这些SNPP链路资源是在由链路资源管理器(LRM)来管理的,即根据连接控制器的请求来分配或释放SNP链
如何在Word 2013中开启自动断字功能
所谓Word2013断字功能,就是在行尾的单词由于太长而无法完全放下时,会在适当的位置将该单词分成两部分,并在行尾使用短横线进行连接.Word2013提供"自动断字"和"手动断字"两种方式,默认情况下未启用断字功能.以启用"自动断字"功能为例,操作步骤如下所述: 第1步,打开Word2013窗口,切换到"页面布局"功能区.在"页面设置"分组中单击"断字"按钮,并在打开的菜单中单击&quo