C#内存管理与垃圾回收
垃圾回收还得从根说起,就像生儿育女一样。
根:根是一个位置,存放一个指针,该指针指向托管堆中的一个对象,或是一个空指针不指向任何对象,即为null。根存在线程栈或托管堆中,大部分的跟都在线程栈上,因为定义的变量就存在线程栈上,类型对象指针存在托管堆中,因为实例化一个对象要额外分配两个字段“类型对象指针”和“同步块索引”。
类型对象指针的作用。实例化一个对象并没有为其方法分配内存,类型的静态字段分配内存,而实例要向调用属于类型的一些东西,就必须通过类型对象指针。如对象的实例是共用类型的方法,实例只需要通过类型对象指针调用类型的方法,更多关于方法的调用请看我的这篇博客。
同步块索引的作用。1:用于lock,使对象在同一时刻只能一个线程访问;2:用于获取对象的hashCode;3:在垃圾回收时标志某个对象是否是垃圾。关于lock最经典的一个例子就是单例了,大家的实现都是实例化一个object对象,然后锁住它,然后在判断是否要实例要实现单例的那个对象。我们为什么要实例化一个object,而不是直接lock(typeof(object)),那是因为这样会把object这个类型给锁住,锁住期间,任何使用线程使用lock(typeof(object))就必须等待,object还是可以正常使用。lock能起到单线程访问的原因是:它里面有一个空的for死循环,一直在读同步块索引中的一个位,如果这个位没有被标志跳出循环,如果被标志就一直执行循环,直到方法执行完成,其他线程就一直等待,现在你知道lock能使你的程序只能单线程反问也知道lock的效率低了吧。
NextObjPtr一个最牛B的指针。CLR中的所有资源都从托管堆中分配,托管堆是一块连续的内存空间,维护一个指针NextObjPtr,它指向上一个对象地址的后面,下一个对象的开始位置,若托管堆中没有对象就指向托管堆的开始位置,每分配一个对象就将NextObjPtr指向这个对象的后面,以准备开始分配下一个对象。NextObjptr指针移动的位置其实就是上一个对象所在空间的长度,从指向对象的开始位置改为对象的末尾吗。从哪里开始分配对象就全靠NextObjPtr啦。
实例化一个对象需要多少空间?对象的所有字段所需的内存+类型对象指针+同步块索引。关于类型对象指针和同步块索引的作用前面已经提过了。有些字段没有明显定义,但它确确实实存在,每个对象除了object的对象都有base字段,通过它可以调用父类的实例字段和方法,通过它你可以访问你爷爷的爷爷定义的字段和方法。CLR用递归的方式调用父类的方法,当然也要看,你爷爷是否愿意让你调用,原因你懂的。
在垃圾回收开始之前速度比C快。对象就这样开心的在托管堆中分配,托管堆的容量是有限的,总有一天第0代会满,容不下一粒沙子。垃圾回收就出场了,在垃圾回收出场之前,你使用内存很happy,当然速度是非常快,比C语言的速度还快,因为C的内存是随便分配,只要找到合适大小的区域,就在那里分配内存了,这样会导致内存碎片,有时需要一块大的内存,需要遍历多处。垃圾回收的时候日子就不是那么好过了。速度肯定比C慢了,看下面你就知道垃圾回收的时候,程序的速度为什么慢了。
垃圾回收分两步:1:标记;2:压缩
1:标记。在垃圾回收开始的时候,垃圾回收器视托管堆中的所有对象都为垃圾,即线程栈上没有指针指向托管堆。这样的估计是因为一个对象被视为垃圾就是它没有被引用,当垃圾回收开始的时候,垃圾回收器会沿着线程栈线性扫描,当线程栈上的一个变量引用了托管堆中的对象时,垃圾回收器就会将这个对象标记,即修改该对象同步块索引中的一个特定的位,同步块索引就是一个bit数组,每一个元素都有它特定的作用,上面就列出了我所知道的三个功能。被标记的对象也可能引用其他的对象,而被引用的对象同样会被标记,垃圾回收器是用递归的方式将这些对象一一标记的,一个对象可能会被多个对象引用,当垃圾回收器发现某个对象被标记时就会退出递归,因为再往下递归完全是多余,而且还可能出现死循环。
垃圾回收器就这样线性的扫描线程栈,递归的扫描托管堆,最后将托管堆中所有被引用的对象标记,而没有被标记的对象就是垃圾,等着被回收。
2:压缩。当垃圾被回收之后,就会出现磁盘碎片,那么就要对托管堆进行整理,即压缩。将没有被回收的对象放在一起,靠近托管堆开始的位置,将剩余的内存腾出空间来以便存放新的对象。由于压缩很多对象就会移动位置,而引用他们的指针都会变得无效,所以托管堆要修改所有指针的指向,以保证不会因为垃圾回收而让对象变得不可到达,指针变得无效。
压缩完了之后,又腾出了空间,又可以分配新的对象,当第0代满了之后又进行垃圾回收,垃圾回收就这样一直进行着,直到回收了3代还是没有内存可以分配,那就是弹尽粮绝的时候了,CLR会告诉你OutOfMemoryException。CLR的内存被的程序吃光了。更多关于代的信息,可以看我的这篇博客。在第0代满的时候就会进行垃圾回收,第0代回收完之后还是没有足够的内存存放当前对象就回收第1代,如果还是不够就回收第2代,够就不回收下一代,垃圾回收还可以用代码控制GC.Collect()。
更多关于内存管理和垃圾回收的内容,请等待我的下一篇博客。
C#内存管理与垃圾回收的更多相关文章
- 使用虚幻引擎中的C++导论(四-内存管理与垃圾回收)(终)
使用虚幻引擎中的C++导论(四)(终) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如 ...
- Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收
很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...
- Java内存管理和垃圾回收
笔记,深入理解java虚拟机 Java运行时内存区域 程序计数器,线程独占,当前线程所执行的字节码的行号指示器,每个线程需要记录下执行到哪儿了,下次调度的时候可以继续执行,这个区是唯一不会发生oom的 ...
- javascript中的内存管理和垃圾回收
前面的话 不管什么程序语言,内存生命周期基本是一致的:首先,分配需要的内存:然后,使用分配到的内存:最后,释放其内存.而对于第三个步骤,何时释放内存及释放哪些变量的内存,则需要使用垃圾回收机制.本文将 ...
- 面试题之C# 内存管理与垃圾回收
面试题之C# 内存管理与垃圾回收 你说说C# 的内存管理是怎么样的 这句话我记了一个多礼拜了, 自从上次东北师大面试之后, 具体请看<随便扯扯东北师大的面试>. 国庆闲着没事, 就大概了解 ...
- JVM内存管理及垃圾回收【转】
很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...
- .NET基础 (05)内存管理和垃圾回收
内存管理和垃圾回收1 简述.NET中堆栈和堆的特点和差异2 执行string abc="aaa"+"bbb"+"ccc"共分配了多少内存3 ...
- JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)
转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...
- java Vamei快速教程22 内存管理和垃圾回收
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 整个教程中已经不时的出现一些内存管理和垃圾回收的相关知识.这里进行一个小小的总结. ...
随机推荐
- MongoDB学习笔记~官方驱动嵌套数组对象的更新
回到目录 对于数组对象mongodb本身是支持的,不过对于数组的更新,mongodb的Csharp驱动目前只支持一级,即你的对象里包含数组,而数组又包括数组,这表示两层,这在更新子数组时,Csharp ...
- javascrip中parentNode和offsetParent之间的区别
首先是 parentNode 属性,这个属性好理解,就是在 DOM 层次结构定义的上下级关系,如果元素A包含元素B,那么元素B就可以通过 parentElement 属性来获取元素A. 要明白 off ...
- BI cube的前世今生:商业智能BI为什么需要cube技术
企业中常常会出现这样一幕幕尴尬的场景: 企业的决策人员需要从不同的角度来审视业务,协助他们分析业务,例如分析销售数据,可能会综合时间周期.产品类别.地理分布.客户群类等多种因素来考量.IT人员在每一个 ...
- Java公众号推荐 - BeJavaGod
今天新创建了一个java的公众号,会经常更新java的文章,有兴趣的朋友关注一下吧- 主要内容基本是跟本微博同步的 不管是做java的新手还是高手,内行还是外行,java还是非java,一起关注,一起 ...
- BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记】
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3975 Solved: 2421[Submit][Stat ...
- 纯java配置SpringMVC
一般情况下,我们会在web.xml下配置好Spring和SpringMVC,并指定好它们的配置文件 是最常用的也是最方便的方法 例如: web.xml <!-- The definition o ...
- 在MySQL中出现Unknown column 'abc' in 'field list'怎么解决?
update TABLE1 set NAME = '?' where ID ='?' 参数字段需要添引号.
- CHM打不开的解决方法
CHM打不开的解决方法 听语音 | 浏览:62240 | 更新:2013-02-04 14:58 | 标签:软件 1 2 3 4 5 6 分步阅读 一键约师傅 百度师傅高质屏和好师傅,拯救你的碎屏机 ...
- java多线程系类:JUC原子类:04之AtomicReference原子类
概要 本章对AtomicReference引用类型的原子类进行介绍.内容包括:AtomicReference介绍和函数列表AtomicReference源码分析(基于JDK1.7.0_40)Atomi ...
- TCP协议的三次握手和四次挥手
暂时需要的信息有: ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1 SYN(SYNchronization) : 在连接建立时用来同步序号.当SYN= ...