.NET教程 - 编译器(Compiler)

更新记录
转载请注明出处:
2022年10月6日 发布。
2022年10月5日 从笔记迁移到博客。

CLR

CLR 管理内存的区域#

主要有三块,分别为

线程的堆栈

用于分配值类型实例

堆栈主要由操作系统管理,而不受垃圾收集器的控制

当值类型实例所在方法结束时,其存储单位自动释放

栈的执行效率高,但存储容量有限

GC 堆

用于分配小对象实例

如果引用类型对象的实例容量占用小于 85000 字节

实例将被分配在 GC 堆上,当有内存分配或者回收时

垃圾收集器可能会对 GC 堆进行压缩

LOH(Large Object Heap)堆

用于分配大对象实例

如果引用类型对象的实例容量占用不小于 85000 字节时

该实例将被分配到 LOH 堆上,而 LOH 堆不会被压缩

而且只在完全 GC 回收时被回收

堆栈的内存分配机制#

对于值类型来说,一般创建在线程的堆栈上

但并非所有的值类型都创建在线程的堆栈上

例如作为类的字段时,值类型作为实例成员的一部分也被创建在托管堆上

装箱发生时,值类型字段也会拷贝在托管堆上

对于分配在堆栈上的局部变量来说,操作系统维护着一个堆栈指针来指向下一个自由空间的地址

并且堆栈的内存地址是由高位到低位向下填充

实例

对于分配在堆栈上的局部变量来说,操作系统维护着一个堆栈指针来指向下一个自由空间的地址

并且堆栈的内存地址是由高位到低位向下填充

public static void Main()
{
    int x = 100;
    char c = 'A';
}

假设线程栈的初始化地址为 50000

因此堆栈指针首先指向 50000 地址空间

代码由入口函数 Main 开始执行,首先进入作用域的是整型局部变量 x

它将在栈上分配 4Byte 的内存空间,因此堆栈指针向下移动 4 个字节

则值 100 将保存在 49997~50000 单位

而堆栈指针表示的下一个自由空间地址为49996,如同所示

image

接着进入下一行代码,将为字符型变量 c 分配 2Byte 的内存空间

堆栈指针向下移动 2 个字节至 49994 单位,值’A’会保存在 49995~49996 单位

地址的分配如图

image

最后,执行到 Main 方法的右括号,方法体执行结束,变量 x 和 c 的作用域也随之结束

需要删除变量 x 和 c 在堆栈内存中的值,其释放过程和分配过程刚好相反

首先删除 c 的内存,堆栈指针向上递增 2 个字节,然后删除 x 的内存

堆栈指针继续向上递增 4 个字节,程序执行结束,此时的内存状况为

image

其他较复杂的分配过程,可能在作用域和分配大小上不同,但是基本过程大同小异

栈的内存分配,效率较高,但是内存容量不大,同时变量的生存周期随着方法的结束而消亡

托管堆的内存分配机制#

引用类型的实例分配于托管堆上,而线程栈却是对象生命周期开始的地方

对 32 位处理器来说,应用程序完成进程初始化后

CLR 将在进程的可用地址空间上分配一块保留的地址空间,

它是进程(每个进程可使用 4GB)中可用地址空间上的一块内存区域

但并不对应于任何物理内存,这块地址空间即是托管堆

引用类型的实例分配于托管堆上,而线程栈却是对象生命周期开始的地方

对 32 位处理器来说,应用程序完成进程初始化后

CLR 将在进程的可用地址空间上分配一块保留的地址空间

它是进程(每个进程可使用 4GB)中可用地址空间上的一块内存区域

但并不对应于任何物理内存,这块地址空间即是托管堆

托管堆又根据存储信息的不同划分为多个区域

其中最重要的是垃圾回收堆(GC Heap)和加载堆(Loader Heap)

GC Heap 用于存储对象实例,受 GC 管理

Loader Heap 又分为 High-Frequency Heap、Low-Frequency Heap 和 Stub Heap

不同的堆上又存储不同的信息

Loader Heap 最重要的信息就是元数据相关的信息,也就是 Type 对象

每个 Type 在 Loader Heap 上体现为一个 Method Table(方法表)

而 Method Table 中则记录了存储的元数据信息

例如基类型、静态字段、实现的接口、所有的方法等等。Loader Heap 不受 GC 控制

其生命周期为从创建到 AppDomain 卸载

IL 指令解析

对象创建和内存分配相关指令#

主要包括:

newobj 用于创建引用类型对象

ldstr 用于创建 string 类型对象

newarr 用于分配新的数组对象

box 在值类型转换为引用类型对象时,将值类型字段拷贝到托管堆上发生的内存分配

作者:重庆熊猫

出处:https://www.cnblogs.com/cqpanda/p/16755113.html

版权:本作品采用「不论是否商业使用都不允许转载,否则按3元1字进行收取费用」许可协议进行许可。

posted @   重庆熊猫  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示