托管堆基础
 简述:每个程序都要使用这样或那样的资源,包括文件、内存缓冲区、屏幕空间、网络连接.....事实上,在面向对象的环境中,每个类型都代表可供程序使用的一种资源。要使用这些资源,必须为代表资源的类型分配内存。以下是访问一个资源所需步骤:
1、调用IL指令newobj,为代表资源的类型分配内存。(C# new操作符)
2、初始化内存,设置资源的初始状态。(一般指构造函数)
3、访问类型的成员来使用资源。(使用成员变量、方法、属性等)
4、摧毁资源的状态以进行清除。(???Dispose???)
5、释放内存。(GC)

从托管堆分配资源
CLR  要求所有的对象都从托管堆分配。进程初始化,CLR划出一个地址空间区域作为托管堆。CLR还要维护一个指针,姑且叫NextObjPtr,该指针指向下一个对象在堆中的分配位置。刚开始的时候, NextObjPtr 设为地址空间区域的基地址。
一个区域被非垃圾对象填满后,CLR会分配更多的区域。这一个过程一直重复,直至整个进程地址空间被填满。所以,应用程序内存收进程的虚拟地址空间的限制。32位进程最多能分配1.5GB,64位进程最多能分配8T。
注:进程内存大小的相关资料
https://msdn.microsoft.com/zh-cn/library/windows/hardware/Dn613959(v=vs.85).aspx
https://msdn.microsoft.com/zh-cn/library/ms189334.aspx
http://blog.csdn.net/yusiguyuan/article/details/12405799;

 C# 的new操作符导致CLR执行以下操作:
1、计算类型的字段(以及从基类型继承的字段)所需要的字节数。
2、加上对象的开销所需的字节数。每个对象都有两个开销字段:类型对象指针和同步块索引。对于32位应用程序,这两个字段各需要32位,所以每个对象需要增加8字节。对于64位应用程序,这两个字段各需要64位,所以每个对象要增加16字节。
3、CLR检查区域中是否有分配对象所需的字节数。如果托管堆有足够的可用空间,就在NetxObjPtr指针指向的地址处放入对象,为对象分配的字节会被清零。接着调用类型的构造器(为this参数传递NextObjPtr),new操作符返回对象引用。就在返回这个对象引用之前,NextObjPtr指针的值会加上这个对象占用的字节数来得到一个新值,即下个对象放入托管堆时的地址。如下图:

垃圾回收算法
 CLR使用引用跟踪算法。引用跟踪算法只关心引用类型的变量,因为只有这种变量才能引用堆上面的对象;值类型变量直接包含值类型实例。引用类型变量可在许多场合使用,包括类的静态和实例字段,或者方法的参数和局部变量。这里我们将所有引用类型的变量都称为根。
CLR开始GC时,首先暂停所有的线程。(这样可以防止线程在CLR检查期间访问对象并更改其状态。) 然后CLR进入GC标记阶段。在这个阶段,CLR遍历堆中的所有对象,将同步块索引字段中的一位设为0。这表明所有的对象都应删除。然后,CLR检查所有的活动根,查看他们引用了哪些对象。这正是CLR的GC被称作引用跟踪GC的原因。如果一个根包含null,CLR忽略这个根并继续检查下一个根。
下图展示一个堆,其中包含几个对象。


应用程序的根直接引用对象A 、C、D 、F。所有的对象都已经被标记。标记对象D时,GC发现这个对象含有一个引用对象H的字段,造成对象H也被标记。标记过程会持续,直至应用程序的所有根所有检查完毕。
检查完毕后,堆中的对象要么已标记,要么未标记。已标记的对象不能被垃圾回收,因为至少有一个根在引用它。我们说这种对象是可达的,因为应用程序可以通过引用它的变量抵达它。 未标记的对象是不可达的,因为应用程序中不存在使对象能被再次访问的根。

CLR知道哪些对象可以幸存,哪些可以被删除后,进入GC的压缩(类似于碎片整理)阶段。在压缩阶段,CLR对堆中已标记的对象进行“乾坤大挪移”,整理所有幸存下来的对象,使他们占用连续的内存。这样做的好处在于:1、所有幸存对象在内存中紧挨在一起,恢复了引用的“局部性”,减少了应用程序的工作集,从而提升了将来访问这些对象时的性能;2、经过整理后,可用空间也是连续的,整个地址空间区段得到了解放,允许其他东西进驻。
在内存中移动了对象之后有一个问题亟待解决。引用幸存对象的根现在引用的还是对象最初在内存中的位置,而非移动后的位置。被暂停的线程恢复执行时,将访问旧的内存位置,会造成内存损坏。 这显然是不能容忍的,所以作为压缩阶段的一部分,CLR还要从每个根减去所引用对象在内存中偏移的字节数。这样就能保证每个根还是引用和之前一样的对象,只是对象在内存中变换了位置。
如图:

代:提升性能 (待续)

引自:《CLR VIA C# -21章》
 

.NET 托管堆和垃圾回收的更多相关文章

  1. 【C#进阶系列】21 托管堆和垃圾回收

    托管堆基础 一般创建一个对象就是通过调用IL指令newobj分配内存,然后初始化内存,也就是实例构造器时做这个事. 然后在使用完对象后,摧毁资源的状态以进行清理,然后由垃圾回收器来释放内存. 托管堆除 ...

  2. 【CLR】解析CLR的托管堆和垃圾回收

    目录结构: contents structure [+] 为什么使用托管堆 从托管堆中分配资源 托管堆中的垃圾回收 垃圾回收算法 代 垃圾回收模式 垃圾回收触发条件 强制垃圾回收 监视内存 对包装了本 ...

  3. 重温CLR(十五) 托管堆和垃圾回收

    本章要讨论托管应用程序如何构造新对象,托管堆如何控制这些对象的生存期,以及如何回收这些对象的内存.简单地说,本章要解释clr中的垃圾回收期是如何工作的,还要解释相关的性能问题.另外,本章讨论了如何设计 ...

  4. CLR via C# 读书笔记-21.托管堆和垃圾回收

    前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...

  5. 托管堆和垃圾回收(GC)

    一.基础 首先,为了深入了解垃圾回收(GC),我们要了解一些基础知识: CLR:Common Language Runtime,即公共语言运行时,是一个可由多种面向CLR的编程语言使用的"运 ...

  6. cir from c# 托管堆和垃圾回收

    1,托管堆基础 调用IL的newobj 为资源分配内存 初始化内存,设置其初始状态并使资源可用.类型的实列构造器负责设置初始化状态 访问类型的成员来使用资源 摧毁状态进行清理 释放内存//垃圾回收期负 ...

  7. C#托管堆和垃圾回收

    垃圾回收 值类型 每次使用都有对应新的线程栈 用完自动释放 引用类型 全局公用一个堆 因此需要垃圾回收 操作系统 内存是链式分配 CLR 内存连续分配(数组) 要求所有对象从 托管堆分配 GC 触发条 ...

  8. 如何管好.net的内存(托管堆和垃圾回收)

    一:C#标准Dispose模式的实现 需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CL ...

  9. NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配

    在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...

随机推荐

  1. Application_Error

    //出现未捕捉的异常时,系统调用本方法,一般用于记录日志.错误页的重定向一般在web.config中设置.        protected void Application_Error(object ...

  2. Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset (0/1-Trie树)

    Vasiliy's Multiset 题目链接: http://codeforces.com/contest/706/problem/D Description Author has gone out ...

  3. POJ 2888 Magic Bracelet(Burnside引理,矩阵优化)

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 3731   Accepted: 1227 D ...

  4. 用shell求两个文件的差集

    假设有两个文件a.file和b.file,分别代表集合A和集合B. a.file的内容如下: abcde b.file的内容如下: cdefg 可以用grep命令 grep命令是常用来搜索文本内容的, ...

  5. 关于“未使用GUID分区表”无法安装的解决方案

    原帖链接:http://itc.do-johodai.ac.jp/~s0823612/ 原版的Mac不能安装在mbr分区.必须得用GUID分区,其实装在mbr也可以,需要修改两个文件一个是OSInst ...

  6. 研究QGIS二次开发笔记(一)

    为了在QT程序中嵌入一个地图,最终选择了QGIS来干这件事.选型阶段真是呵呵.我折腾的是QGIS2.4.0. 首先,到官方网站下载安装QGIS.如果你跟我一样懒的话,可能希望下载一个已经编译好的win ...

  7. ACM之递推递归

    Hdu 2569 突破蝙蝠的包围,yifenfei来到一处悬崖面前,悬崖彼岸就是前进的方向,好在现在的yifenfei已经学过御剑术,可御剑轻松飞过悬崖. 现在的问题是:悬崖中间飞着很多红,黄,蓝三种 ...

  8. CCF 201312-2 ISBN号码 (水题)

    问题描述 每一本正式出版的图书都有一个ISBN号码与 之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后 ...

  9. How to bind to data when the DataContext is not inherited【项目】

    http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherit ...

  10. OC:属性、点语法、KVC

    //属性的属性 属性定义在一个 .h文件里,在这个.h文件里可以定义实例变量(就是这个类的特征),也可以通过   @protery(属性约束关键字) 属性名字类型 属性名 来定义一些属性,在prope ...