前言:

在.NET程序开发中,为了将开发人员从繁琐的内存管理中解脱出来,将更多的精力花费在业务逻辑上,CLR提供了自动执行垃圾回收的机制来进行内存管理。开发人员甚至感觉不到这一过程的存在。CLR执行垃圾回收的过程,有以下几点:

  • 如何判断哪些对象是可以进行回收的,哪些是要保留的?
  • 对象在堆上是如何分布的?何时执行垃圾回收?
  • 垃圾回收的过程如何进行的?有哪些优化策略?

判断哪些对象需要进行回收

垃圾回收,第一步要判断哪些对象需要被GC回收掉。简而言之,那些在代码的任何位置也无法访问到的对象是需要被GC回收掉的。

GC借助于应用程序根(Application Roots)和对象图(Object Graph)来判断哪些对象需要被回收。应用程序根保存了堆上对象的引用,如果一个对象没有直接或者间接的被应用程序根所引用,那么就说明没有任何代码可以访问到它,因此这个对象可以被回收。

应用程序根只是一个入口点,一个对象可能持有其他一个或者多个对象的引用,这种对象间的引用关系构成了对象图。每次创建新对象,在复制引用、删除引用,或者执行垃圾回收之后,CLR都会自动更新它。

对象如何分配在堆上

.NET中的对象创建在托管堆上,托管堆维护着一个指针,这个指针标识了下一个将要创建的新对象所在位置,通常称作新对象指针。该指针总是位于托管堆的末尾。当使用new运算符创建对象时,CLR将会执行下面几个主要操作:

  • 计算此对象所要分配的内存大小;
  • 检查托管堆,确保托管堆有足够的空间来建立这个对象。如果空间够,将会调用构造函数来创建对象,并在托管堆末尾创建对象,然后返回对象在托管堆上的引用。引用的地址即为新对象指针所指向的地址。如果空间不够,则会执行一次垃圾回收来释放空间;
  • 修改新对象指针的值,使它指向上一个可用的地址。

垃圾回收的执行过程

GC有许多算法,常见的算法有Reference Counting, Mark Sweep, Copy Collection等,目前主流的虚拟系统.NET CLR, Java VM都采用的Mark Sweep算法。Mark-Sweep标记清除阶段:先假设Managed Heap中所有对象都可以被回收,然后找出不能回收的对象,给这些对象打上标记,最后Managed Heap中没有打标记的对象都可以被回收。Compact压缩阶段:对象回收之后Managed Heap内存空间变得不连续,在Managed Heap中移动这些对象,使他们重新从Managed Heap基地址开始连续排列。

执行垃圾回收的时机:

  • 当通过new关键字创建对象时,如果发现托管堆所占用的内存已经达到一个临界点,就会进行垃圾回收;
  • 应用程序退出时也会执行一次垃圾回收;
  • 调用System.GC.Collection()方法强制执行;

垃圾回收过程中的优化策略

垃圾回收过程中还采用了一些优化策略,主要时对象代(Object Generation)和大对象堆(Large Object Heap)

1. 对象代

对象共分了三个代级:

  • 第0代:新近分配在托管堆上的对象,从来没有被GC回收过,任何一个新对象,当它第一次被分配在托管堆上时,就是第0代;
  • 第1代:经历过一次垃圾回收后,依然保留在堆上的对象;
  • 第2代:经历过两次或者以上垃圾回收后,依然保留在堆上的对象。

当进行垃圾回收时,垃圾回收器将会首先检查所有的第0代对象,并对其中可回收的对象进行清理。如果清理后获得足够的空间,经历过垃圾回收后的对象将提升为第1代对象。

如果所有的第0代对象都检查过了,但是内存空间还不够,那么将会检查第1代对象的可访问性,并进行垃圾回收。此时,如果经历过垃圾回收的第1代对象仍保留在堆上,则会升级为第2代对象。类似的,如果内存仍不够用,将会对第2代对象进行检查和垃圾回收。如果第2代的部分对象在此次垃圾回收后仍然保留在堆栈上,它依然是第2代对象。因为总共定义了3代对象。如果第2代对象在进行完垃圾回收后空间依然不够用,则会抛出OutOfMemoryException异常。

可见,最容易清理掉的就是那些新对象。

2. 大对象堆

垃圾回收的过程中有一个很影响性能的地方,就是在压缩的过程中,因为要批量地挪动对象,以填充腾出来的空间,如果对象很大,那么要移动的数据量就会很大。

如果将大对象直接分配在第0代,那么第0代的空间很快就会被占满,从而迫使CLR执行一次垃圾回收,这样执行垃圾回收的次数就会变得很频繁。

因此,第二个优化策略就是采用大对象堆,当对象大小超过85kb时,就会被分配在大对象堆上。大对象堆有几个特点:

  • 没有代级的概念,所有对象都被视为第2代对象;
  • 不进行对象移动和空间压缩,因为移动大对象是相对耗时的操作。
  • 对象不会被分配在末尾,而会在链表中找合适的位置,因此会存在碎片问题。

至此,就对.NET GC有了一个基本的了解。感谢您的阅读~

[.NET] GC垃圾回收机制的更多相关文章

  1. JVM和GC垃圾回收机制和内存分配

    JVM运行期间 线程共享 线程私有 线程共享: 方法区 堆方法区:存放可以共享数据,静态常量,类的共有方法属性字段等,可以共享的存在方法区. 堆:存放class对象 . 线程私有:本地方法栈 虚拟机栈 ...

  2. JVM架构和GC垃圾回收机制

    深入理解系列之JDK8下JVM虚拟机(1)——JVM内存组成 https://blog.csdn.net/u011552404/article/details/80306316 JVM架构和GC垃圾回 ...

  3. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

  4. 面试官,不要再问我“Java GC垃圾回收机制”了

    Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...

  5. 乐字节Java|GC垃圾回收机制、package和import

    本文接上一篇:乐字节Java|this关键字.static关键字.block块.本文是接着讲述JavaGC垃圾回收机制.package 和 import语句. 一.GC垃圾回收机制 GC全名:Garb ...

  6. 通俗易懂.NET GC垃圾回收机制(适用于小白面试,大牛勿喷)

    情景:你接到xx公司面试邀请,你怀着激动忐忑的心坐在对方公司会议室,想着等会的技术面试.技术总监此时走来,与你简单交谈后.... 技术:你对GC垃圾回收机制了解的怎么样? 你:还行,有简单了解过. 技 ...

  7. GC垃圾回收机制详解

    JVM堆相关知识    为什么先说JVM堆?  JVM的堆是Java对象的活动空间,程序中的类的对象从中分配空间,其存储着正在运行着的应用程序用到的所有对象.这些对象的建立方式就是那些new一类的操作 ...

  8. C# GC 垃圾回收机制

    今天来谈谈C# 的GC ,也就是垃圾回收机制,非常的受教,总结如下 首先:谈谈托管,什么叫托管,我的理解就是托付C# 运行环境帮我们去管理,在这个运行环境中可以帮助我们开辟内存和释放内存,开辟内存一般 ...

  9. asp.net 之 GC (垃圾回收机制)

    今天抽时间好好整理了下GC相关知识,看了CSDN和博客园的几篇文章,有了一定的简单了解,决定根据个人理解整合一份随笔写下来,望诸位指教. 一:基础问题 1.首先需要知道了解什么是GC? GC如其名,就 ...

  10. GC垃圾回收机制,iOS内存管理。

    问题: MRC中通过调用静态方法创建的新对象,不再使用时需要对其发送release消息吗? 不需要,因为约定静态方法创建的对象会自动将其放入自动释放池,即已对其发送autorelease消息,因此不可 ...

随机推荐

  1. FastAdmin 是如何利用 Git 管理插件代码的?

    FastAdmin 是如何利用 Git 管理插件代码的? 由于 FastAdmin 的插件很多,如果每一个插件用一个项目来管理,可以倒是可以,但是项目还多了. 但是如果使用文件夹在同一级的的方式又不方 ...

  2. centos6.6 myphpadmin

    基本环境为:Centos6.6+Apache2.2.15+php5.3.3+Mysql5.1.73 开始下载了网站上最新版本myPhpAdmin4.3.8安装后打开浏览器为空白页,后百度后都讲是与PH ...

  3. 7z 7zip 日期、时间,文件名

    from: http://hi.baidu.com/guicomeon/item/c0957c373972fbc52f8ec26e 先说明一点,要注意区分当前所使用的系统,中文系统和英文系统是有区别的 ...

  4. 安装memcached服务 和 php 安装memcache扩展

    这是所有的命令,至于哪个命令是干嘛的自己悟去吧  ,顺便穿插一些知识点 安装libevent cd /home/ wget  http://www.monkey.org/~provos/libeven ...

  5. UTF-8中的BOM

    UTF-8中的BOM UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式.字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是EF BB B ...

  6. VBA7种文档遍历法

    Sub 在选定文档最后加入一句话() '遍历文件 Dim MyDialog As FileDialog On Error Resume Next Application.ScreenUpdating ...

  7. MySQL单机单实例安装脚本

    说明:使用mysql generic tar.gz包快速安装mysql 三个文件installation_of_single_mysql.sh.template_install-my.cnf.mysq ...

  8. Conv

    folly/Conv.h folly/Conv.h is a one-stop-shop for converting values across types. Its main features a ...

  9. mybatis一对多关联查询+pagehelper->分页错误

    mybatis一对多关联查询+pagehelper->分页错误. 现象: 网上其他人遇到的类似问题:https://segmentfault.com/q/1010000009692585 解决: ...

  10. Quest.Central.for.DB2.v5.0.2.4下载地址

    http://pan.baidu.com/s/1h5vgl 激活码 2-95710-02204-91891-68750yhason