各种语言的垃圾回收在IT界噪的沸沸扬扬,有极大的优化同时也有瓶颈。

而在.Net中的垃圾回收机制又是怎样的呢?

众所知周,.Net中的垃圾回收机制是由.Net Framework托管的,带给开发者最大的好处就是省去了手动进行垃圾回收的麻烦。

在虚拟内存当中,有个区域称为“栈”,这个数据结构完全符合“先进后出(FILO)”的特性。

在C#中,有个名词叫作用域,作用域表示了一个变量的作用范围,比如

{
int a;
//do something
{
int b;
//do something
}
}

声明变量a之后,在内部代码块中声明变量b,然后内部代码块终止,b超出了作用域,然后变量a所在的代码块终止,a超出了作用域,所以b的作用域始终包含在a的作用域当中。

在栈当中,当声明一个变量时,在栈开辟一个空间存放,当这个变量超过变量域,栈把用于这个变量的内存释放,这就是栈的工作方式。

当代码执行到变量b所在的内部代码块的时候,栈指针如图所示,但该内部代码块执行结束之后,b超出了作用域,栈指针会移动到变量a所在的内存区域,也就是799997所在的字节内存处。此时如果声明新的变量c,c会存放在从799996开始的一段内存空间中,这些空间以前是存储变量b的。

.Net垃圾回收机制会根据这个规律按部就班执行下去,保证栈内存的操作不会出现差错,当编译器遇到int i,j这样的代码行,同时声明两个变量时,这两个变量进入作用域的顺序是不确定的,但这两个变量是同时声明的,也必须是同超出作用域的,所以编译器会随机把这两个变量放到栈内存当中,超出作用域时会确保把先进入栈的那个变量后删除,这样就能保证该规则不会与变量的生存期冲突。

C#的另外一个名词——“堆”,堆的出现是为了降低编译器对代码声明的所有类型处理的复杂性,和栈配合可以更加有效清楚地管理内存。通常我们希望使用一个方法分配内存来存储一些数据,并在方法退出后的一段时间内数据仍是可用的。只要是用new运算符来请求分配存储空间的,就存在这种可能性——例如对于所有的引用类型。此时就要使用托管堆。

 void func(){
Student stu1;
stu1 = new Student();
Student stu2 = new Student();
stu3 = stu1;
}

堆的工作原理跟栈相似,只是存储了不同的对象。当以上代码执行时,在堆栈当中的内存情况如下所示:

不同的是堆内存是向上分配的(冒号:后面的值表示存储的内容,此处不再标出栈内存的地址)。对于变量stu1,stu2,stu3的声明和在栈中的内存分配情况在前面已经交代清楚,声明 Student stu1; 时,栈为变量stu1分配一段空间,此时stu1存储的值并没有初始化,当代码运行到 stu1 = Student(); 时,在堆内存中分配了一个Student实例,即200000 ~ 2000031段(假设分配给Student对象的内存大小为32),并把这段内存的首地址复制给栈中的stu1。执行 Student stu2 = new Student() 时,把栈上的4个字节分配给stu2,然后stu2的对象在堆上从200032开始向上分配空间,并把200032地址赋值给stu2。然后声明stu3,存储内容为stu1的实例,因此最终栈中存储了3个变量,堆中存储了2个对象,有两个变量(stu1,stu3)指向了同一个对象。当func()函数运行结束后,所有变量均超出了作用域,因此会以stu3,stu2,stu1的顺序依次释放,栈指针移向原先stu1变量所在内存的上一个字节内存处。对于堆中的对象,当一个对象检测到没有变量指向它时,即把该对象所占用的内存自动释放出来。先释放stu2实例,再释放stu1实例。

这样一来,因为对象的存在周期不同,会导致堆内存中已用堆块和空闲堆块随机存在。

按照以往类似C++编译器的特性,当此时需要new一个新的对象时,会在堆中找一块大小适合的内存用于存放新的对象,在这个过程中会稍微降低new一个新对象的效率,在C#编译器中,但执行垃圾回收时,编译器会把所有的已使用的空间按照原先的顺序拼凑在一起,形成一段连续使用的空间。

然后把堆指针指向最上已使用的空间(已使用3),这样C#在new新对象的时候,就直接在堆指针的地方直接分配,这样一来直接导致了C#在new新对象的时候具有极高的效率(和其他语言相比)。但编译器在整理堆内存的时候也会造成额外的开销,则在整理时候应用程序必须是停止运行状态,所以最好让编译器自己决定进行垃圾回收的时间,而不是让应用程序自己决定(GC.Collect()),造成额外开销和提高new效率,权衡下来还是会提高总体的运行效率。这也是.Net垃圾回收机制和其他垃圾回收机制比较大的不同点。

以上为个人对.Net垃圾回收机制的一些见解,内容拙劣,欢迎斧正。

尊重知识产权,转载引用请通知作者并注明出处!

.Net的垃圾回收机制(GC)之拙见——托管类型的垃圾回收的更多相关文章

  1. 垃圾回收机制GC知识再总结兼谈如何用好GC

    一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...

  2. 垃圾回收机制GC知识再总结兼谈如何用好GC(转)

    作者:Jeff Wong 出处:http://jeffwongishandsome.cnblogs.com/ 本文版权归作者和博客园共有,欢迎围观转载.转载时请您务必在文章明显位置给出原文链接,谢谢您 ...

  3. java垃圾回收机制GC

    记得第一次总结java 的GC的时候,是刚开始在课堂上学习GC的时候,那时候许老师第一节java课 课后老师说同学们可以去深入理解一下java的GC机制: 但是是花费了三四个小时,翻看了<Thi ...

  4. 垃圾回收机制GC知识再总结兼谈如何用好GC(其他信息: 内存不足)

    来源 图像操作,易内存泄露,边界像素 一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对 ...

  5. .NET 之 垃圾回收机制GC

    一.GC的必要性 1.应用程序对资源操作,通常简单分为以下几个步骤:为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存. 2.应用程序对资源(内存使用)管理的方式,常见的一 ...

  6. 垃圾回收机制GC

    垃圾回收机制GC 我们已经知道,name = 'leethon'这一赋值变量的操作,是将变量与数据值相绑定. 而数据值是存储到内存中的,有时变量会重新赋值即绑定其他数据值,而使得原本的数据值无法通过变 ...

  7. 回收机制GC

    .NET 之 垃圾回收机制GC 一.GC的必要性 1.应用程序对资源操作,通常简单分为以下几个步骤:为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存. 2.应用程序对资源 ...

  8. C#技术漫谈之垃圾回收机制(GC)

    GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是 ...

  9. C#技术漫谈之垃圾回收机制(GC)(转)

    GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是 ...

随机推荐

  1. freemarker写select组件报错总结(六)

    1.错误描述 六月 26, 2014 10:53:26 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严重: Template proc ...

  2. Caused by: java.lang.ClassNotFoundException: net.sf.ezmorph.Morpher

    1.错误描述 Exception in thread "main" java.lang.NoClassDefFoundError: net/sf/ezmorph/Morpher a ...

  3. Java中的List转换成JSON报错(一)

    1.错误描述 Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang/ ...

  4. IE浏览器兼容的常见问题及解决方案

    常见6个问题及解决方案 1 IE6/IE7对display:inline-block的支持还欠缺 就是我们做导航栏时通常会用到<ul><li>标签去写,在现在一些主流的浏览器中 ...

  5. Gadgets for dollars and pounds CodeForces - 609D

    Nura wants to buy k gadgets. She has only sburles for that. She can buy each gadget for dollars or f ...

  6. 都在说RunLoop...... 到底什么是RunLoop?

    RunLoop(消息循环):说白了就是一种事件监听循环.就好比是一个while循环,监听到事件就起来,没有就休息. 介绍: 它可以在不同模式下进行切换,iOS有五种模式,其中UIInitializat ...

  7. jpgraph 折线图--解决中文乱码的问题(标题和图例)

    在jpgraph根目录中: 如Jpg\jpgraph_ttf.inc.php 中开头添加 define('CHINESE_TTF_FONT','SIMYOU.TTF'); \Jpg\jpgraph_l ...

  8. 【NOIP2009】【CJOJ1687】【洛谷1074】靶形数独

    题面 Description 小城和小华都是热爱数学的好学生,最近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了,于是他们向 Z博士请教,Z 博士拿出 ...

  9. 推荐一款有趣的APP-种子习惯

    在女朋友的影响下接触到了种子习惯的app,一开始不觉得它有多大魅力,只知道它有契约的功能,有很多人分享自己的习惯,记录生活中的点滴. 毕业回家的寒假,家里比较冷,每天起床都需要莫大的勇气,挣扎半天最终 ...

  10. C++学习-7

    1.面向过程是:数据与操作分离,数据容易被意外修改 2.面向过程通过私有化的权限进行数据封装 3.类型后辍:类名 operator "" _XXXX(int data)  增加后缀 ...