编程控制垃圾收集器
System.GC类型为应用程序提供了直接控制垃圾收集器的一些方法,可以通过GC.MaxGeneration来查询托管堆支持的最大代龄,目前为2。
通过下面方法执行垃圾收集器
- GC.Collect(int);传递代龄,传递0,收集0代,传递1,收集0,1代,传递2,收集0.1.2代;
- GC.Collect();无参强制对所有代龄的对象执行垃圾收集;
GC.WaitForPendingFinalizers方法会挂起调用线程,直到处理终止化队列的线程清空了该队列,并完成每个对象的Finalize方法调用为止。下面代码:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
上面代码首先强制执行一次垃圾收集。当第一轮垃圾收集完成后,不需要终止化的那些对象内存将被回收。但是终止化对象的内存还没有被回收。在第一次Collect调用返回后,一个特殊的、专门用于终止化的线程将采用异步的方式来调用所有终止化对象的Finalize方法。WaitForPendingFinalizers方法将使应用程序处于睡眠状态,直到所有的Finalize方法调用完成为止。当WaitForPendingFinalizers方法返回,所有的终止化对象将成为真正的可收集垃圾。这时第二次Collect调用将强制执行第二轮垃圾收集,所有终止化对象的内存将在这一轮垃圾收集中完全被回收。
通过编程继续了解垃圾收集:
namespace ControlGC
{
class Program
{
static void Main( string [] args)
{
Console.WriteLine( " Maximum generations: " + GC.MaxGeneration);
// 在托管堆上创建一个新的GenObj对象
Object o = new GenObj();
// 刚刚创建,代龄为0
Console.WriteLine( " Gen " + GC.GetGeneration(o)); // 0
// 执行垃圾收集器,提高对象代龄
GC.Collect();
Console.WriteLine( " Gen " + GC.GetGeneration(o)); // 1
GC.Collect();
Console.WriteLine( " Gen " + GC.GetGeneration(o)); // 2
GC.Collect();
Console.WriteLine( " Gen " + GC.GetGeneration(o)); // 2(最大值)
o = null ; // 销毁对象,此时对象的代龄为2
Console.WriteLine( " Collect Gen 0 " );
GC.Collect( 0 ); // 收集第0代对象,其实没有0代对象
GC.WaitForFullGCApproach(); // 不会调用Finalize
Console.WriteLine( " Collect Gen 0 " );
GC.Collect( 1 ); // 收集第0代对象,其实没有1代对象
GC.WaitForFullGCApproach(); // 不会调用Finalize
Console.WriteLine( " Collect Gen 0 " );
GC.Collect( 2 ); // 收集第2代对象,对象真正被收集
GC.WaitForFullGCApproach(); // 调用Finalize
}
}
class GenObj
{
~ GenObj()
{
Console.WriteLine( " In Finalize method " );
}
}
}
执行结果
深刻的了解代龄
大尺寸对象
任何占用内存大于等于85000字节的对象都被认为是大尺寸对象(large object)。大尺寸对象是从一个特殊的大尺寸对象托管堆中分配的。该托管堆中对象的终止化和内存释放行为与前面描述的小尺寸对象相同。但是大尺寸对象不会被压缩,因为在托管堆中移动大尺寸对象会浪费CPU比较多的时间。
大尺寸对象总是被认为是2代的。