首页 > 代码库 > .Net之垃圾回收算法
.Net之垃圾回收算法
垃圾回收器检测托管堆中是否有应用程序不在使用的任何对象,如果一次垃圾回收之后,堆栈没有可用的内存,new操作符将会抛出OutOfMemoryException(内存溢出)。 每一个应用程序都包含一组根,每个根都是一个存储位置,。其中包含指向引用类型对象的一个指针。该指针要么引用托管堆中的一个对象,要么为null。类型中定义的任何一个静态字段都被认为是一个根,值类型变量永远必备认为是根。 垃圾回收器可以沿着线程的调用栈上运行,检测每一个方法内部表来确定所有调用方法的根。垃圾回收器的第一个阶段是所谓的标记阶段,在这个阶段,垃圾回收器沿着线程栈上行以检查所有根。如果发现一个根引用了一个对象,就在对象的“同步快索引字段”上开启一位----------对象就是这样标记的。垃圾回收器以递归的方式遍历所有可达对象。标记好根和它的字段引用的对象后,垃圾回收器检查下一个根,继续标记对象,如果垃圾回收器试图标记一个先前标记过的对象,就会停止沿着这个路径走下去。这个行为有2个目的。首先,垃圾回收器不会多遍历一组对象,索引性能显著增强,其次,如果存在对象的循环链表,可以避免陷入无限循环。 检查好所有根之后,堆中将包含一组已标记的和未标记的对象。未标记的被认为是垃圾。现在垃圾回收器开始第二阶段,即压缩阶段,在这个阶段中,垃圾回收器线性的遍历堆,以寻找为标记的对象的连续内存块。如果发现的内存块比较小,垃圾回收器会忽略他们。如果发现大的,可用的连续内存块,垃圾回收器会把非垃圾的对象移动到这里以压缩堆。 移动内存中的对象后,包含“指向这些数据对象的指针”的变量和CPU寄存器都回变的无效。所以垃圾回收器必须从新访问应用程序的所有根,并修改他们指向对象的新内存位置。堆内存压缩后,托管对的NextObjPtr指针将指向紧接在最后一个非垃圾对象之后的位置。垃圾回收器会造成显著的性能损失。这是使用托管堆的主要缺点。但是这只有垃圾回收在第0代的时候才发生。 什么时候导致Finalize方法被调用? ① 第0代满 ②代码显示的调用System.GC的静态方法Collect ③Windows报告内存不足 ④CLR卸载AppDomain,被卸载时CLR认为AppDomain中不再存在任何根,因此会对所有代的对象执行垃圾回收。⑤CLR关闭 一个进程正常终止是,CLR就会关闭,在关闭进程中不存在任何根,因此会调用托管堆中的多有对象的Finalize方法。注意:CLR此时不回尝试压缩或释放内存,因为整个进程都要终止,将由Windows负责回收进程所有内存。 Finalize的缺点:它的调用时间是不能保证的,它不是公共方法,所以类的用户不能显示的调用它。
.Net之垃圾回收算法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。