Garbage Collection

Tags
只记录.NET的mark-and-sweep回收算法

mark-and-compact

首先将当前主线程挂起
假设堆上所有对象是可回收的 (mark)
找到它们的roots(在数据段、寄存器以及栈上可以访问到对象的入口点,一般为已初始化的静态变量和当前线程还在使用的对象)
根据roots创建一个reachable graph(即从roots出发可以访问到的堆上的对象图),将可达对象取消标记
然后对所有可回收对象回收,并compact heap:将可达对象的内存压到一起
由于改变了这些可达对象的堆内存,还需要修复roots中对其的指针
 

generation

分代思想:一般将堆内存分为Gen0, 1, 2,数字越大驻留在内存的时间越长(即进行了前面几代的GC后仍没有被清理的内存)
每一代会有个内存占用阈值,当这一代内存达到一个设定的阈值时进行这一代的GC:将所有代数≤自己的内存一起清理,幸存者加入到下一代(如果是2代就还是加到2代里)
一般来说2代的阈值会很大,可能达到几G;0和1加起来保持在16M左右
 

finalization queue & freachable queue

对于实现了析构器的类的对象,在产生这个实例时就会在finalization queue里加入这个对象的指针;GC决定清理这个对象时,会先把它的指针加入到freachable queue里,对象迎来一次短暂的复苏(resurrection),等待析构函数被调用后移出freachable queue,并被真正的GC
System.GC.SuppressFinalize() 和 ReRegisterForFinalize()方法分别用于向GC申请不要 / 要调用这个对象的析构函数,具体一点就是申请向finalization queue中移出 / 移入这个对象的指针
finalize会有一定开销,对于实现IDisposable的非托管资源,我们可以调用它的Dispose方法同时在Dispose方法中调用SuppressFinalize方法,避免进行没必要的Finalize
 
Reference: