.Net的垃圾回收机制(GC)之拙见——托管类型的垃圾回收
各种语言的垃圾回收在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)之拙见——托管类型的垃圾回收的更多相关文章
- 垃圾回收机制GC知识再总结兼谈如何用好GC
一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...
- 垃圾回收机制GC知识再总结兼谈如何用好GC(转)
作者:Jeff Wong 出处:http://jeffwongishandsome.cnblogs.com/ 本文版权归作者和博客园共有,欢迎围观转载.转载时请您务必在文章明显位置给出原文链接,谢谢您 ...
- java垃圾回收机制GC
记得第一次总结java 的GC的时候,是刚开始在课堂上学习GC的时候,那时候许老师第一节java课 课后老师说同学们可以去深入理解一下java的GC机制: 但是是花费了三四个小时,翻看了<Thi ...
- 垃圾回收机制GC知识再总结兼谈如何用好GC(其他信息: 内存不足)
来源 图像操作,易内存泄露,边界像素 一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对 ...
- .NET 之 垃圾回收机制GC
一.GC的必要性 1.应用程序对资源操作,通常简单分为以下几个步骤:为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存. 2.应用程序对资源(内存使用)管理的方式,常见的一 ...
- 垃圾回收机制GC
垃圾回收机制GC 我们已经知道,name = 'leethon'这一赋值变量的操作,是将变量与数据值相绑定. 而数据值是存储到内存中的,有时变量会重新赋值即绑定其他数据值,而使得原本的数据值无法通过变 ...
- 回收机制GC
.NET 之 垃圾回收机制GC 一.GC的必要性 1.应用程序对资源操作,通常简单分为以下几个步骤:为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存. 2.应用程序对资源 ...
- C#技术漫谈之垃圾回收机制(GC)
GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是 ...
- C#技术漫谈之垃圾回收机制(GC)(转)
GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是 ...
随机推荐
- HTML5之Canvas画圆形
HTML5之Canvas画圆形 1.设计源码 <!DOCTYPE html> <head> <meta charset="utf-8" /> & ...
- Linux显示服务器完整的状态信息
Linux显示服务器完整的状态信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ apachectl [fullstatus] Usage: /usr/sbi ...
- Struts2(六) 用Struts完成客户列表显示
Struts完成客户列表显示 所用的基础知识 在之前的随笔中已经讲过.这篇是介绍如何使用Struts 完成客户列表显示 . 下面是 完成的代码执行逻辑图: 抽取项目部分代码 相信大家认真看一遍就明 ...
- 芝麻HTTP:分析Robots协议
利用urllib的robotparser模块,我们可以实现网站Robots协议的分析.本节中,我们来简单了解一下该模块的用法. 1. Robots协议 Robots协议也称作爬虫协议.机器人协议,它的 ...
- iOS - Swift Enumerations or how to annoy Tom
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- 【BZOJ2442】修建草坪(动态规划,单调队列)
[BZOJ2442]修建草坪(动态规划,单调队列) 题面 权限题..洛谷 题解 设\(f[i]\)表示前\(i\)个里面选出来的最大值 转移应该比较显然 枚举一个断点的位置,转移一下就好 \(f[i] ...
- HNOI2017 单旋
题目描述 网址:https://www.luogu.org/problemnew/show/3721 大意: 有一颗单旋Splay(Spaly),以key值为优先度,总共有5个操作. [1] 插入一个 ...
- [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
- 【noip模拟】tree
000 ms Memory Limit: 128 MB [吐槽] 点分治点分治点分治 嗯..场上思考树状数组的时候好像傻掉了..反正就是挂了就是了.. [题解] 首先如果没有环的话就是一 ...
- 云计算之路-阿里云上:服务器CPU 100%问题是memcached的连接数限制引起的
非常抱歉,昨天的服务器CPU 100%问题是达到 memcached 的连接数限制引起的,不是阿里云服务器的问题. 之前我们用的是阿里云“云数据库 memcached 版”,上个周末我们换成了自己搭建 ...