以下是他展示的一些有趣观点:当你问别人什么是垃圾收集时,你得到的答案可能会按如下方式:“垃圾收集是操作环境自动回收程序不再使用的内存。 它通过跟踪从根开始的内存来识别哪些对象是可访问的”。
这种描述混淆了机制与目标。 这就像说消防员的工作是“驾驶红色卡车并喷水”。 这是对消防员所做的事情的描述,但它忽略了工作的重点(即扑灭火灾,更普遍地说,消防安全)。
一个正确编写的程序不能假定finalizers将永远运行。
代码块中的对象可以在调用函数期间变得可回收。
方法的参数可以在执行方法时变得可回收。
奇怪的现实世界类比:垃圾收集器可以在潜水员最后一次接触跳板时收集您的跳板,即使潜水员仍在空中!
最简洁的:
不要把GC视为跟踪根。 把GC看作是删除你不再使用的东西。
垃圾回收器(GC)是.NET框架的一部分,由公共语言运行时(CLR)初始化,用于管理应用程序中内存的分配和释放。
垃圾回收器的类型
垃圾回收器可以在各种场景下工作。CLR提供以下类型的垃圾回收:
并发垃圾回收 并发垃圾回收允许用户线程在大多数第2代垃圾回收期间运行。只要托管堆中仍有新分配的空闲空间,用户线程就可以运行并创建新对象。
非并发垃圾回收 非并发垃圾回收会暂停所有非垃圾回收线程,在垃圾回收期间完全暂停应用程序。
后台垃圾回收 后台垃圾回收是并发垃圾回收的替代方案。它类似于并发垃圾回收,但允许中断正在进行的第二代垃圾回收,并临时阻塞程序执行,以进行一代和二代垃圾回收。完成一代和二代垃圾回收后,程序执行和第二代垃圾回收都会继续。这进一步缩短了因垃圾回收而导致程序执行暂停的时间。
内存和托管堆 一旦由公共语言运行时(CLR)初始化垃圾收集器,它会分配一个称为托管堆的内存段,与操作系统中的本地堆相对立,用于存储和管理对象。
对于每个托管进程,垃圾收集器使用Windows的VirtualAlloc函数在托管堆中保留一个内存段。(它使用Windows的VirtualFree函数将内存段释放回操作系统)。进程中的所有线程都在同一堆上为对象分配内存。
需要考虑的一件重要事情是,每个分配段的大小是实现特定的,并且随时可能发生变化。
代
存储在托管堆中的对象根据其年龄组织成代。垃圾回收主要发生在短寿命对象的回收中,这些对象通常仅占堆的一小部分。
当垃圾回收器检测到某一代的生存率很高时,它会增加该代的分配阈值。
垃圾回收器阶段
垃圾回收由以下条件之一触发:
系统物理内存不足。这可以通过操作系统的低内存通知或主机指示的低内存来检测到。
托管堆上分配对象使用的内存超过可接受的阈值。该阈值在进程运行时不断调整。
调用GC.Collect方法。在几乎所有情况下,您不必调用此方法,因为垃圾回收器会持续运行。
此时,垃圾回收器经过以下阶段:
标记阶段:垃圾回收器通过以下信息创建所有活动对象的列表(不在列表中的所有对象都有可能被删除),以确定对象是否存活:
重定位阶段:在重定位阶段中,更新了所有在所有活动对象列表上的对象的引用,使它们指向在压缩阶段中对象将要重新定位到的新位置。 压缩阶段:回收死亡对象占用的空间并压缩幸存对象。压缩阶段将幸存的垃圾回收对象向段的旧端移动。随着死亡对象占用的空间被释放和剩余的活动对象被移动,堆在压缩阶段中得到了压缩。垃圾回收后剩余的所有活动对象按其原始顺序向堆内存的旧端移动。
资源
官方文档: https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals