在说明垃圾回收的实现机制之前,先说明一下垃圾回收存在的背景。

垃圾回收器(GC)是.NET平台中一个很重要的组成部分,.NET垃圾回收机制降低了编写程序的复杂程度,使程序员不用耗费精力去处理析构,成功的将内存管理从程序的编写时,脱离到运行时。

一、析构函数

析构函数的作用主要是释放类在构造函数中以及类生命周期中所获取的资源,比如需要释放互斥锁、由操作符NEW所分配的对象内存等。当然析构函数也不只限于释放资源,一般析构函数可以执行在最后一次操作对象后所需要执行的任何操作。

二、关于垃圾回收

在.NET FRAMEWORK框架中,内存中的资源(二进制信息)分为“托管资源”和“非托管资源”,其中托管资源必须受到CLR的管理(如强类型安全检查),非托管资源需要手动释放。

托管资源分别存放在两个地方,一个是“堆栈”,另外一个是“托管堆”。值类型和引用类型的引用存放在“堆栈”中,而引用类型所代表的对象存在于“托管堆”中。

三、垃圾回收算法

CLR中的每个对象有两个开销字段:类型对象指针,同步块索引。

(1)、对于对象生存期的管理,有的系统采用“引用计数算法”,而对于微软的COM用的就是此算法。具体算法就是每个对象都在维护着一个内存字段,用来统计有多少个位置在使用该对象,当某一个位置不在使用该对象后,该内存字段中的计数就减一,直至该字段最后为0,当值为0时,该对象就可以从内存中删除掉了。

但是该算法最大的问题就是处理不好循环引用。

(2)、CLR使用的算法为“引用跟踪算法”,此算法只关心引用类型的变量,因为只有这种变量才能引用堆上的对象。可以将引用类型的变量称为根。

此算法是当CLR进行GC时,首先暂停所有线程,以防止线程CLR在检查期间访问对象并更改其状态。

A、CLR遍历堆中的所有对象,并将同步块索引字段中的一位设为0,这表明所有对象可以被删除。

B、查看所有活动根,并查看它们引用了哪些对象。如果一个根包括NULL,则忽略此根继续检查下一个根。

C、如果某根引用了堆上的对象,则会标记此对象,在该对象的同步块索引中的位设为1。此对象被标记后,CLR会检查这个对象中的根,标记它们引用的对象。若发现对象已经标记,则不再重新检查该对象,也就避免了因为循环引用而产生死循环。

D、检查完毕后,堆中的对象要么被标记,要么未被标记,然后CLR进入GC的“压缩”阶段。(需要注意的是,静态字段引用的对象会一直存在,直到用于加载类型的APPDOMAIN卸载为止。内在泄漏的一个重要原因就是静态字段引用某个对象集合,然后不停的向对象集合添加数据项。所以,要尽量避免使用静态字段。)

四、代的机制

CLR的GC是基于代的垃圾回收器,对于垃圾回收做了以下假设:

1、对象越新,生存期越短。

2、对象越老,生存期越长。

3、回收堆的一部分,速度快于回收整个堆。

五、垃圾回收触发条件

1、当CLR检测到第0代超过内存预算时,则触发一次GC。

2、代码显式调用GC的静态方法Collect。大多时候要避免使用此方法。从第2代开始回收。

3、当使用CreateMemoryResourceNotification或者QueryMemoryResourceNotification来监视系统的总体内存使用情况时,如果Windows报告内存低,则CLR会强制垃圾回收以释放死对象,减小进程工作集。

4、CLR卸载APPDOMAIN时,CLR会认为一切都不是根。

5、CLR正在关闭,Windows将会回收进程中的全部内存。

六、垃圾回收模式

有两种基本GC模式:工作站、服务器。应用程序默认使用以“工作站”GC模式运行。若想使用服务器回收器,可以在配置文件中添加gcServer元素(gcServer=true)。

另外还有两种子模式:并发(默认)和非并发。一般并发垃圾回收器消耗的内存通常比使用非并发垃圾回收器多。若要使用非并发回收器,可在配置文件中创建gcConcurrent元素(enable=false)

七、需要特殊清理的类型

针对一些本机资源的终结,CLR除了回收对象内存之前,还需要在Finalize中释放本机资源,如下所示:

  public class sometype()
{
~sometype()//此为一个finalize方法
}  

需要注意的是,finalize方法的执行时间是控制不了的。同时,CLR不保证多个finalize方法的调用顺序,在finalize方法中最好不要访问定义了finalize方法的其他类型的对象。调用静态方法也要小心。由于此方法是为释放本机资源而设计的,所以要谨慎使用。

如果想创建封装了本机资源的类型时,需要继承Safehandle。

另外一种释放本机资源的方法是Dispose,调用此方法只是控制这个清理动作的发生时间。同时,调用此方法并不会将托管对象从托管堆中删除。若决定显示调用Dispose方法,建议将调用放在一个异常处理finally块中。

.NET 垃圾回收浅解的更多相关文章

  1. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  2. 基于Python对象引用、可变性和垃圾回收详解

    基于Python对象引用.可变性和垃圾回收详解 下面小编就为大家带来一篇基于Python对象引用.可变性和垃圾回收详解.小编觉得挺不错的,现在就分享给大家,也给大家做个参考. 变量不是盒子 在示例所示 ...

  3. python 垃圾回收详解

    原文:https://zhuanlan.zhihu.com/p/31150408 总纲 策略和垃圾回收系统工作内容 引用计数详解 标记-清除+分代收集 循环引用 编程应用-常见方法 ex 过程详解 使 ...

  4. C# using垃圾回收详解

    简介 定义一个范围,将在此范围之外释放一个或多个对象. 语法 using (Font font1 = new Font("Arial", 10.0f)) { } C# 语言参考 主 ...

  5. JVM垃圾回收详解

    通常,我们在写java程序的时候,似乎很少关注内存分配和垃圾回收的问题.因为,这部分工作,JVM已经帮我们自动实现了. 这样看起来,好像很美好,但是任何事情都有两面性.虽然JVM会自动的进行垃圾回收, ...

  6. Python垃圾回收详解:引用计数+标记清理+分代回收

    Python采用的是引用计数机制为主,标记-清理和分代收集两种机制为辅的策略. 1.引用计数 python中一切皆对象,所以python底层计数结构地就可以抽象为: 引用计数结构体{ 引用计数; 引用 ...

  7. JVM中GC浅解:垃圾回收的了解

    1.为什么要有GC 没有GC的世界,我们需要手动进行内存管理,但是内存管理是纯技术活,又容易出错.但是我们写码的目的是为了解决业务问题,所以可以把这种纯技术活自动化,当然自动化也是有代价的. 2.垃圾 ...

  8. Java Garbage Collection基础详解------Java 垃圾回收机制技术详解

    最近还是在找工作,在面试某移动互联网公司之前认为自己对Java的GC机制已经相当了解,其他面试官问的时候也不存在问题,直到那天该公司一个做搜索的面试官问了我GC的问题,具体就是:老年代使用的是哪中垃圾 ...

  9. JVM的垃圾回收机制详解和调优

    JVM的垃圾回收机制详解和调优 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都 ...

随机推荐

  1. 菜鸟浅谈“诈骗”希望“治未病"

    关于目前诈骗.社工数据的套路,说道说道~ 一.前言 这篇文章没有什么高深的技术,只有普普通通的套路,主要也是有I春秋各位表哥与诈骗分子的交手有感而发! 二.正文 因为我们上网的或者其他条件下的人群,没 ...

  2. $.ajax()——超时设置,增加 loading 提升体验

    前端发送Ajax请求到服务器,服务器返回数据这一过程,因原因不同耗时长短也有差别,且这段时间内页面显示空白.如何优化这段时间内的交互体验,以及长时间内服务器仍未返回数据这一问题,是我们开发中不容忽视的 ...

  3. Git从码云或者Github 克隆代码到本地

    Git从码云或者Github 克隆代码到本地 1.下载安装Git,傻瓜式下一步下一步即可... 2.配置Git: 2.1.选择你要clone到本地的路径:右键--->$ Git Bash Her ...

  4. FutureTask与Fork/Join

    在学习多线程的过程中,我们形成了一种思维习惯.那就是对于某个耗时操作不再做同步操作,让他分裂成一个线程之后执行下一步,而线程执行耗时操作.并且我们希望在我们需要它返回的时候再去调用它的结果集.好比我们 ...

  5. Vue子组件监听事件中传递参数的方法

    在子组件中,我们可以通过以下方式监听事件: v-on:click="$emit('funcName',a)" 如果需要传多个参数,可以通过以下方式: v-on:click=&quo ...

  6. How to manage local libraries in IntelliJ IDEA

    如何在 IntelliJ IDEA 中管理本地类库 一般来说,如果项目是基于 Maven 管理工具的,我们会在 pom.xml 中添加 dependency 来管理依赖.但有时也会遇到要用的类库不在 ...

  7. date命令的基本用法

    date设置时间 设置时间:-s参数 date -s "20190426 15:22:33" date查看时间差  (-d参数多用于脚本) 查看时间差:-d参数date -d &q ...

  8. python学习,day3:函数式编程,局部变量和全局变量

    # coding=utf-8 # Author: RyAn Bi school = 'THU' #全局变量 def change_name(name): global age #在函数中,用globa ...

  9. net 反编译神器

    文章地址:https://www.cnblogs.com/sheng-jie/p/10168411.html dnSpy官网下载  分享链接 .net core源码导航 https://www.cnb ...

  10. compact framework windows mobile wm c#代码 创建快捷方式

    已经2018年了,windows mobile已经宣布不维护狠多年了,不要问我为什么还在开发windows mobile的程序,我也不想.公司有一批手持扫描枪设备依然是windows mobile的程 ...