C#--垃圾回收

垃圾回收.png

​ 在C#中,内存的是由CLR进行管理,而在C\C++中内存是由程序员手动管理。这样的弊端就很明显:1.忘记释放不需要的内存,造成内存泄露;2.尝试访问已释放的内存,造成内存破坏,程序错误,进而造成安全漏洞。而C#中由系统管理,不需要的内存,由CLR进行清理。清理不需要的内存,就是C#中的垃圾回收。

1.从托管堆分配资源

​ 在CLR中,所有对象都是从托管堆中分配,在进程初始化时,CLR会为此进程划分一份地址空间区域作为托管堆,并且CLR中维护一个指针NextObjPtr(初始化时,为此空间区域的基地址),它指向下一个对象在托管堆中所要分配的地址。当此托管堆区域被非垃圾对象填满时,系统将分配更多地址空间。32位系统最多分配1.5GB,64位系统最多分配8TB。

​ C#在初始化一个对象时有以下操作:

  1. 计算类型字段的所需字节数;

  2. 加上对象的开销所需字节数(类型对象指针,和同步块索引);

  3. CLR检查区域是否有足够的字节数分配给新对象;

​ 在托管堆中一般连续分配的对象都有较强的联系,所以连续的内存地址会引用“局部化”获得性能的提升,这样使进程工作集会非常小,应用程序只需要使用很少的内存,从而 提供速度。以上有个前提是内存无限,现实中,CLR通过“垃圾回收”,去清理不需要的对象,来尽可能增加内存使用效率。

2.垃圾回收算法

​ 当程序调用new操作符时,没有足够的内存空间来分配是,CLR就执行垃圾回收。

  1. 引用计数垃圾回收器算法:(在Microsoft的“组件对象模型”用的就是此算法)这种算法,在程序中对上的每个对象都维护着一个内存字段来统计程序有多少“部分”正在使用对象。随着每一“部分”到达代码中某个不需要对象的地方,就递减对象的计数字段。计数字段变成0,对象就可以从内存中删除了。这有个弊端,在GUI应用程序中,窗口将容纳对子UI元素的引用,而子UI元素将容纳对父窗口的引用。这种引用会组织两个对象的计数器达到0,所以这两个对象永远不会删除。

这种算法因为存在问题,所以CLR使用另一种“引用跟踪算法”。

  1. 引用跟踪算法:此算法只关心引用类型的变量,只有这种变量才会引用堆上的对象,这种变量称为

    (1)CLR开始执行GC时,首先暂停进程中的所有线程(防止线程在检查期间访问对象并更改状态);

    (2)CLR进入GC的标记阶段,CLR遍历堆中的所有对象,将同步块索引字段中的一位设为0(0表示对象应删除);

    (3)CLR检查所有活动根,检查他们引用了哪些对象(这就是引用跟踪)。如果根引用了堆上的对象,CLR就会标记被引用的对象,将该对象的同步块索引中的位设为1,一个对象被标记后,CLR会检查对象中的根,并标记他们引用的对象,如果发现对象已经被标记,则不重新检查对象的字段。(这就避免了引用计数垃圾回收器算法中的循环引用而产生的死循环,导致对象无法被删除)。

    (4)检查完毕后,同步块索引中标记为0的被删除,标记为1的保留。

    (5)执行GC中的压缩阶段,这个阶段将保留的对象所占的内存地址进行改变,使他们占用连续的内存地址(好处:1.使保留的对象恢复引用“局部化”,减小程序工作集,提升访问这些对象的性能;2.使剩下的可用空间也是连续的;3. 压缩空间,解决堆中的空间碎片化问题)。

    垃圾回收示例.png

3.代:提升性能

​ CLR中的GC是基于代的垃圾回收器

  1. 对象越新,生存周期越短;
  2. 对象越老,生存周期越长;
  3. 回收堆的一部分,速度快于回收整个堆。

其工作原理:

  1. 当程序首次运行时,新初始化的对象都为第0代对象;
  2. 当第0代对象占用的空间达到CLR中的预算容量时(CLR初始化时,会为每代的对象设置一个预存容量),GC开始执行,利用引用跟踪算法,将不可达的对象清理,而未清理的对象成为第1代对象。所以每次GC后,第0代就没有对象了;
  3. 然后新创建的对象则会分配到0代中,循环上面的清理过程。
  4. 当第1代对象占用的内存空间达到预设容量时,GC就是利用引用跟踪算法,清理第1代对象,而未清理的对象则会升为第2代对象(第2代对象为GC中的最高代对象,GC中只包含3代对象),在第1代对象没有达到预设容量时,则不会管第1代中的对象,就算在执行GC时,第1代中含有不可达对象,也不会在此时清理。
  5. 当然CLR中对每代对象的预设对象不是恒定不变的,比如:当每次回收第0代对象后,所存活的对象很少,则会减少第0代对象的内存空间预设容量;反之,每次回收第0代对象后,所存的对象很多,则会增加第0代对象的内存空间预设容量。
第一次垃圾回收.png

一个新初始化的堆,其中包含了一些对象, 这些对象都是0代, 有颜色的是可达对象, 无颜色的是不可达的.

第一次垃圾回收后.png

经过一次垃圾回收, 第0代中的可达对象升级为第1代 ; 其他的被清除, 此时第0代没有对象

垃圾回收2.png

第0代分配了新对象,第1代有垃圾产生(第1代内存未达到预设值)

垃圾回收3.png

第2次回收后,第0代的可达对象升级为第1代, 之前第1代中的垃圾并没有被清理

垃圾回收4.png

第1代产生更多垃圾, 第0代有新增对象

垃圾回收5.png

第3次回收, 因为第1代已达到预设值, 则将第1代可达对象升级为第2代, 第0代可达对象升级为第1代.(垃圾回收中 最高为第2代)

4.垃圾回收触发条件

  1. CLR在检测到第0代超过预算时;

  2. 代码显示调用system.GC的静态Collect方法;

  3. Windows报告低内存情况;

  4. CLR正在卸载AppDomain;

  5. CLR正在关闭.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容