垃圾回收还得从根说起,就像生儿育女一样。

:根是一个位置,存放一个指针,该指针指向托管堆中的一个对象,或是一个空指针不指向任何对象,即为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#内存管理与垃圾回收的更多相关文章

  1. 使用虚幻引擎中的C++导论(四-内存管理与垃圾回收)(终)

    使用虚幻引擎中的C++导论(四)(终) 第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢. 第二,某些细节操作,这篇文章省略了,如 ...

  2. Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收

    很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...

  3. Java内存管理和垃圾回收

    笔记,深入理解java虚拟机 Java运行时内存区域 程序计数器,线程独占,当前线程所执行的字节码的行号指示器,每个线程需要记录下执行到哪儿了,下次调度的时候可以继续执行,这个区是唯一不会发生oom的 ...

  4. javascript中的内存管理和垃圾回收

    前面的话 不管什么程序语言,内存生命周期基本是一致的:首先,分配需要的内存:然后,使用分配到的内存:最后,释放其内存.而对于第三个步骤,何时释放内存及释放哪些变量的内存,则需要使用垃圾回收机制.本文将 ...

  5. 面试题之C# 内存管理与垃圾回收

    面试题之C# 内存管理与垃圾回收 你说说C# 的内存管理是怎么样的 这句话我记了一个多礼拜了, 自从上次东北师大面试之后, 具体请看<随便扯扯东北师大的面试>. 国庆闲着没事, 就大概了解 ...

  6. JVM内存管理及垃圾回收【转】

    很多Java面试的时候,都会问到有关Java垃圾回收的问题,提到垃圾回收肯定要涉及到JVM内存管理机制,Java语言的执行效率一直被C.C++程序员所嘲笑,其实,事实就是这样,Java在执行效率方面确 ...

  7. .NET基础 (05)内存管理和垃圾回收

    内存管理和垃圾回收1 简述.NET中堆栈和堆的特点和差异2 执行string abc="aaa"+"bbb"+"ccc"共分配了多少内存3 ...

  8. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  9. java Vamei快速教程22 内存管理和垃圾回收

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 整个教程中已经不时的出现一些内存管理和垃圾回收的相关知识.这里进行一个小小的总结. ...

随机推荐

  1. MYSQL的常用命令和增删改查语句和数据类型

    连接命令:<a href="http://lib.csdn.net/base/mysql" class='replace_word' title="MySQL知识库 ...

  2. linux c++应用程序内存高或者占用CPU高的解决方案_20161213

    对于绝大多数实时程序来说,实时处理相关程序中的循环问题所带来的对机器的损耗和自身的处理速度的平衡,以及与其他程序的交互以及对其他功能的影响难免会成为程序设计中最大的障碍同时也是最大的突破点. 在所有这 ...

  3. Linux下查找文件:which、whereis、locate、find 命令的区别

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索.which       查看可执行文件的位置,通过环境变量查whereis    查看文件的位置,通过数据库查,每 ...

  4. 【Linux】Vim语法高亮显示

    配置vim 1. 安装vim2. 在hom创建文件.vimrc3. 修改.vimrc内容 syntax=on4. 打开vim,完成! 注: 预转的Vim(比如我现在的Linux Mint)不是完整版, ...

  5. C++STL - 函数模板

    模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...

  6. Mysql慢查询和慢查询日志分析

     Mysql慢查询和慢查询日志分析   众所周知,大访问量的情况下,可添加节点或改变架构可有效的缓解数据库压力,不过一切的原点,都是从单台mysql开始的.下面总结一些使用过或者研究过的经验,从配置以 ...

  7. docker-9 supervisord 参考docker从入门到实战

    参考docker从入门到实战 使用 Supervisor 来管理进程 Docker 容器在启动的时候开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务.但我们经常需要在一个机 ...

  8. ajax缓存问题

    默认情况下,请求总会被发出去,但浏览器有可能从它的缓存中调取数据.换句话说,在缓存过期之前,针对相同地址发起的多个Ajax请求,只有第一次会真正发送到服务端.要禁止使用缓存的结果,可以设置 cache ...

  9. C库函数使用与总结之字符串处理函数

    1. memcpy(拷贝内存内容) [头文件]#include <string.h> [函数原型]void *memcpy(void *dest, const void *src, siz ...

  10. Java 8简明教程

    本文由 ImportNew 欢迎阅读我编写的Java 8介绍.本教程将带领你一步一步地认识这门语言的新特性.通过简单明了的代码示例,你将会学习到如何使用默认接口方法,Lambda表达式,方法引用和重复 ...