.net垃圾回收分三代:gen 0专收短命小对象,90%在此回收;gen 1为缓冲代,筛选中等寿命对象;gen 2存放长期存活对象及大对象,回收开销大、暂停长。

如果您观察到.NET应用中内存占用波动明显、GC暂停时间异常增长,或性能分析工具显示Gen 2回收频繁触发,则很可能是由于对C#垃圾回收代数结构与回收机制理解不足所致。以下是关于Gen 0、Gen 1、Gen 2本质及其运作逻辑的详细说明:
一、Gen 0:新生代对象的高频回收区
Gen 0是托管堆中最新分配对象的默认存放区域,专为生命周期极短的对象设计。其核心目标是快速识别并清理大量临时对象,从而最小化扫描开销与暂停时间。该代采用“停止世界”(Stop-the-World)式回收,但因对象数量少、存活率低,整体耗时通常在毫秒级。
1、所有新创建的小对象(小于85,000字节)默认进入Gen 0,除非显式分配至大对象堆(LOH)。
2、当Gen 0空间不足以满足新分配请求时,GC自动触发Gen 0回收。
3、回收过程中,GC从根(Root)出发进行可达性分析;未被标记的对象立即释放,存活对象被提升至Gen 1。
4、约90%的对象在Gen 0中即被回收,这是分代机制提升效率的关键依据。
二、Gen 1:过渡缓冲代,用于筛选中等寿命对象
Gen 1充当Gen 0与Gen 2之间的缓冲层,主要作用是延缓对象晋升节奏,避免短命对象过早进入高成本回收代。它不承担主要清理任务,而是通过一次额外的存活检验,过滤掉在Gen 0回收后仍短暂活跃的对象。
1、从Gen 0回收中幸存下来的对象被整体提升至Gen 1。
2、Gen 1回收仅在Gen 0回收后仍无法腾出足够空间时触发,频率显著低于Gen 0。
3、回收时,Gen 1中的不可达对象被清除,剩余存活对象全部晋升至Gen 2。
4、Gen 1本身不长期驻留对象,其存在意义在于降低Gen 2误触发概率。
三、Gen 2:长期存活对象与大对象的最终归宿
Gen 2包含所有经多次回收仍持续存活的对象,以及所有直接分配的大对象(≥85,000字节),例如大型数组、长字符串或图像缓冲区。该代回收开销最大,涉及整个托管堆(含LOH),可能导致数百毫秒级暂停,因此应严格避免频繁触发。
1、从Gen 1回收中幸存的对象被提升至Gen 2;大对象(如new byte[100000])跳过Gen 0/1,直接进入Gen 2关联的LOH。
2、Gen 2回收由系统内存压力驱动,例如物理内存不足、托管堆扩张至阈值,或显式调用GC.Collect(2)。
3、LOH在Gen 2回收中被清理,但默认不执行内存压缩(.NET Core 3.0+起可启用压缩选项)。
4、Gen 2回收会同步扫描并清理大对象堆,且暂停时间与堆总大小呈近似线性关系。










