各种语言的垃圾回收在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. HI3531由DMA 发起PCIe 事务

    Hi3531 PCIe 控制器内含DMA 控制器,DMA 控制器包含有两个DMA 通道(一个 DMA 读通道和一个DMA 写通道).PCIe 控制器内包含的DMA 控制器用于大数据量 的存储器读写事务 ...

  2. Attribute name "aphmodel" associated with an element type "mxg" must be followed by the ' = ' charac

    1.错误描述 org.apache.batik.transcoder.TranscoderException: null Enclosed Exception: Attribute name &quo ...

  3. ATA接口寄存器描述

    ATA接口寄存器描述 .ATA接口的三种数据传输方式 位. )MDMA(Multiword DMA)传输,用于数据传输.ATA主机控制器向ATA设备下达MDMA传输命令后,等待设备向主机发送DMARQ ...

  4. Ubuntu Desktop变为Ubuntu Server服务器版的方法

    去Ubuntu官网看到有好几种版本可以下载,alternate(文本安装).desktop9(桌面).netbook(上网本).server(服务器). 使用server版某个理由: 32位的系统可以 ...

  5. Caused by: The Result type [json] which is defined in the Result annotation on the class

    1.错误描述 严重: Dispatcher initialization failed Unable to load configuration. - [unknown location] at co ...

  6. 如何在BIOS中设置RAID?

    随着价格的下降和相应主板的支持,目前SATA硬盘已经逐渐成为主流.但由于受芯片组和操作系统的影响,不少用户对SATA硬盘的使用及安装系统掌握不足,今天小编就给大家介绍一下SATA硬盘的日常应用技巧,希 ...

  7. Android 开发环境搭建与Hello World

    Hello World 到这里, 环境搭建就没问题了. 接下来, 创建一个Android 的Hello World. 1.  添加一个安卓虚拟设备 直接点击虚拟设备管理图标或是  Window--&g ...

  8. python urllib和urllib3包使用

    urllib包 urllib是一个包含几个模块来处理请求的库.分别是: urllib.request 发送http请求 urllib.error 处理请求过程中,出现的异常. urllib.parse ...

  9. centos svn 服务器间的数据迁移

    svnadmin dump erp > ~/erp.svn   当前目录下的erp 导出到根目录下名为erp.svn tar -zcvf backupSvn.tar.gz backupSvn   ...

  10. iOS开发--XMPPFramework--用户登录(三)

    创了一个XMPP即时通讯交流群140147825,欢迎大家来交流~我们是一起写代码的弟兄~ 我们在第一篇文章中,已经介绍了Openfire服务器的搭建等环境的配置, 第二篇文章中,导入了XMPPFra ...