C#/.NET堆与栈

  • 内容
  • 评论
  • 相关

堆与栈都是内存空间的一部分,其中,堆又可以分为托管堆和非托管堆。托管堆和栈由 CLR 管理。

对托管堆中的一部分——GC 堆中不用的对象进行释放就是垃圾回收的主要工作,而托管堆的其他部分,和开发者关系相对没有那么大。对非托管堆的管理则需要由开发者完成。

在 CLR 开始执行第一行代码之前,它会先建立三个程序域:系统域、共享域以及默认的一个应用程序域(AppDomain 类型的一个实例)。

其中,开发者无法直接操作系统域和共享域,但 AppDomain 类型的实例可以有多个。

对于简单的程序,例如控制台程序,第一个默认域的名称就是执行文件的全名,例如 abc.exe。可以使用 CreateDomain 方法创建更多的应用程序域。

每一个 AppDomain 的实例都有自己的加载堆,下面就会介绍加载堆到底是什么。

这里的堆(heap)是托管堆(managed heap)的简称。顾名思义,它由 CLR 进行管理。

它是在运行程序时,CLR 申请的一块内存空间。它基于进程,属于进程内存空间的一部分。

这块空间可以划分为下面几个主要部分:

  • (至少)三个程序域,以及它们自带的加载堆和其他零部件。
  • GC 堆(GC heap):垃圾收集器的处理对象。它分为 0, 1, 2 代三块区域,越高代的堆大小越大。

大对象堆(large object heap)是 2 代堆的一部分,它存放超过 85KB 大小的对象。

因为大对象堆里面的对象太大,移动代价过高,所以微软设计的意图是直接将它提升到 2 代,避免升代移动引起的性能损失。

其中,加载堆(loader heap)存在于每一个程序域中,存放 CLR 自己的类型系统以及用户定义的类型对象。

不同域的加载堆存放的对象不同。另外,AppDomain 的加载堆也存放静态对象,由于静态对象是全局的,不会成为垃圾,所以加载堆不受垃圾收集器管辖。

加载堆又可以分为高频堆(大小为 32KB),低频堆(大小为 8KB)等。顾名思义,高频堆存放的是 CLR 认为访问次数可能较多的对象,例如类型方法表等。

下图简单展示了托管堆的结构。

托管堆结构简图

本文标题:C#/.NET堆与栈

本文地址:http://www.hosteonscn.com/4999.html

评论

0条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注