C#面试题更新 2026-08-05

请说明 .NET 的垃圾回收(GC)机制如何处理堆内存的压缩,以及大对象堆(LOH)有哪些特殊的管理方式?

技术原理C#.NET

考察说明

考察对 .NET GC 堆管理机制、压缩及大对象堆特性的理解。

回答思路

  1. 【回答框架 1】.NET GC 采用分代回收,将托管堆分为 0 代、1 代和 2 代。GC 在回收时会进行堆压缩,将存活对象向堆的起始端移动,合并空闲空间,以减少内存碎片并提高缓存局部性。
  2. 【回答框架 2】压缩过程会更新对象引用,代价较高,因此 GC 会权衡碎片程度和压缩成本。对于小对象堆,通常会在必要时进行压缩;而对于大对象堆,由于对象较大,移动成本高,GC 默认不压缩,而是通过空闲列表管理内存。
  3. 【回答框架 3】大对象堆(LOH)主要存放大于 85,000 字节(约 83 KB)的对象。LOH 不进行压缩,以避免复制大对象的开销,但这样容易产生碎片。GC 会利用空闲块来满足后续大对象的分配请求。
  4. 【回答框架 4】从 .NET 4.5.1 起,可通过配置或调用 GCSettings.LargeObjectHeapCompactionMode 属性,在下一个阻塞式 GC 时对 LOH 进行压缩。另外,LOH 不是分代回收的一部分,它总是作为 2 代回收的一部分被处理。
  5. 【关键点 1】GC 使用分代回收,压缩在小对象堆中通过移动存活对象来减少碎片。
  6. 【关键点 2】LOH 对象大小阈值是 85,000 字节,GC 默认不压缩 LOH,以节省移动大对象的开销。
  7. 【关键点 3】可通过 GCSettings.LargeObjectHeapCompactionMode 或 runtimeconfig 配置启用 LOH 压缩,但在 .NET Core 3.0 之前仅支持 .NET Framework。
  8. 【易错点 1】不要误以为所有 GC 压缩都会移动所有对象,实际上压缩可能只移动部分或全部存活对象。
  9. 【易错点 2】LOH 不压缩不意味着不会回收内存,GC 仍然会回收其中的无效对象,但不会移动存活对象。