《CLR Via C#》学习笔记系列04---托管堆和垃圾回收器GC
这里我们讨论的两个东西:托管堆和垃圾回收器,前者是负责创建对象并控制这些对象的生存周期,后者负责回收这些对象。
一、托管堆分配资源
CLR要求所有的对象都从托管堆分配。进程初始化时,CLR划出一个地址空间区域作为托管堆。CLR还要维护一个指针P,该指针指向下一个对象在堆中的分配位置。
那么我们进一步深入看看创建一个对象(也就是new 一个对象)时CLR做了哪些工作呢。
1、计算类型字段需要的字节数。
2、加上对象开销所需要的字节数,每个对象都有两个开销:类型对象指针和同步块索引
3、CLR检查区域中可用空间够不够,如果够就在指针P指向的地址放入对象。
4、调用类型的构造器,new操作符返回对象引用。
5、返回对象引用之前指针P会移到下个对象放入托管堆时的地址。
二、垃圾回收器回收资源
应用程序调用new操作符创建对象时,可能没有足够的地址空间来分配该对象,发现空间不够,CLR就执行回收.
在讲GC时我们要明白几个概念:
根:将所有引用类型的变量都称为根
可达和不可达:至少有一个根在引用对象时我们称这个对象可达,否则我们称之为不可达。
正式开始垃圾回收,我们参考上面的这个图,图中A,B、C、D、E就是我们托管堆上的对象,现在只有A和C两个对象被引用,E被C引用,步骤如下:
1、CLR开始GC时,前先暂停进程中的所有线程。
2、CLR遍历堆中的所有对象,将所有对象都标记为0,表示所有对象都应删除。
3、CLR检测所有活动根,任何根如果引用了堆上的对象CLR就会标记那个对象为1.注意这里的C引用了E,在标记C的时候还要判断E是否标识了1,如果标记了就不再标记,如果没有标记则标记为1
4、标记完后堆中的对象要么是已标记1,要么是未标记0,已标记的对象为可达的,未标记的对象为不可达的,GC会接下来会删除这些未标记的对象,也就是标记为0的对象
5、GC将对象删除后进入压缩阶段,将所有对象集中在一个连续的类存中,解决了本机的空间碎片化的问题,压缩完成后,CLR恢复应用程序的所有线程。
至此,一个对象的创建到回收就完成了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!