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

垃圾回收器(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. 【Hadoop & Ecilpse】Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied: user=bruce, access=WRITE, inode="/out2/_temporary/0":atguigu:supergroup:drwxr-xr-x

    问题再现: 使用本机 Ecilpse  (Windows环境) 去访问远程 hadoop 集群出现以下异常: 问题原因: 因为远程提交的情况下如果没有 hadoop 的系统环境变量,就会读取当前主机的 ...

  2. Linux C 重定向简单范例

    //前言:我们知道printf()会将信息输出到stdout流,然后展示到屏幕上. //那么我们所实现的简单的重定向就可以将stdout指向一个文件,然后读写,这样就达到了重定向的目的. //code ...

  3. 总结day3 ---- 进制转换,字符串切片,字符串常用方法.,for 循环,

    前情提要: int 的相关操作 进制转换 bit_lenth() str 的索引,以及常用的相关方法 for 循环 索引 切片 相关方法 一  : int 的相关操作 int 主要用于生活中的计算问题 ...

  4. Oracle递归查询(start with)

    写代码时碰到要弄清楚Oracle的role之间的传递关系,就是有role A的话,可以通过grant A to B,把A赋予给B,又通过grant B to C .那我想知道所有role中,有哪些ro ...

  5. python实现数据库增删改查

    column_dic = {"id": 0, "name": 1, "age": 2, "phone": 3, &quo ...

  6. 牛客OI周赛8-提高组A-用水填坑

    牛客OI周赛8-提高组A-用水填坑 题目 链接: https://ac.nowcoder.com/acm/contest/403/A 来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制: ...

  7. 通过view实现字段的只读、隐藏操作【转】

    原文地址:http://cn.openerp.cn/view_groups/ 在OpenERP V7视图(ir.ui.view)多了一个非常有用的字段(groups_id) 'groups_id': ...

  8. win10开启 linux Bash命令(win10内置了linux系统支持)

    win10开启 Ubuntu linux Bash命令(win10内置了linux系统支持) 第一步: 先在设置→更新和安全→针对开发人员中选择"开发人员模式",点击后会下载&qu ...

  9. suse-Linux下安装Oracle11g服务器

    系统要求 Linux安装Oracle系统要求 系统要求 说明 内存 必须高于1G的物理内存 交换空间 一般为内存的2倍,例如:1G的内存可以设置swap 分区为3G大小 硬盘 5G以上 2.修改操作系 ...

  10. java io 处理流,BufferdInputStream、BufferedWriter、BufferedReader

    BufferdInputStream:读取helloworld.java helloworld.java: package io; public class HelloWorld { public s ...