一、GC工作原理:

 GC如其名,就是垃圾收集,当然这里仅就内存而言。Garbage Collector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象,通过识别它们是否被引用来确定哪些对象是已经死亡的哪些仍需要被使用。已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。这就是GC工作的原理。为了实现这个原理,GC有多种算法。比较常见的算法有Reference CountingMark SweepCopy Collection等等。目前主流的虚拟系统.net CLRJava VMRotor都是采用的Mark Sweep算法。

Mark Sweep:

在程序运行的过程中,不断的把Heap的分配空间给对象,当Heap的空间被占用到不足 以为下一个对象分配的时候Mark Sweep算法被激活,将垃圾内存进行回收并将其返回到free list中。

Mark Sweep就像它的名字一样在运行的过程中分为两个阶段,Mark阶段和Sweep阶段。Mark阶段的任务是从root出发,利用相互的引用关系遍历整个Heap,将被root和其它对象所引用的对象标记起来。没有被标记的对象就是垃圾。之后是Sweep阶段,这个阶段的任务就是回收所有的垃圾。

Mark Sweep算法虽然速度比Reference Counting要快,并且可以避免循环引用造成的内存泄漏。但是也有不少缺点,它需要遍历Heap中所有的对象(存活的对象在Mark阶段遍历,死亡的对象在Sweep阶段遍历)所以速度也不是十分理想。而且对垃圾进行回收以后会造成大量的内存碎片。

Generation:

Generational garbage collector(又被称为ephemeral garbage collector)是基于以下几个假设的:

l          对象越年轻则它的生命周期越短;

l          对象越老则它的生命周期越长;

l          年轻的对象和其它对象的关系比较强,被访问的频率也比较高;

l          对Heap一部分的回收压缩比对整个Heap的回收压缩要快。

Generation的概念就是对Heap中的对象进行分代(分成几块,每一块中的对象生存期不同)管理。当对象刚被分配时位于Generation 0中,当Generation 0的空间将被耗尽时,Mark Compact算法被启动。经过几次GC后如果这个对象仍然存活则会将其移动到Generation 1中。同理,如果经过几次GC后这对象还是存活的,则会被移动到Generation 2中,直到被移动到最高级中最后被回收或者是同程序一同死亡。 采用Generation的最大好处就在于每次GC不用对整个Heap都进行处理,而是每次处理一小块。对于Generation 0中的对象,因为它们死亡的可能性最大,所以对它们GC的次数可以安排多一些,而其它相对死亡的可能性小一些的对象所在的Generation可以少安排几次GC。这样做就使得GC的速度得到了一定程度的提高。这样就产生了几个有待讨论的问题,首先是应该设置几个Generation,每个Generation应该设置成多大,然后是对每个对象升级时它应该是已被GC了多少次而仍然存活。关于.net CLR对这个问题的处理,在本文的最后将给出一个例子对其进行测试。

using System;

 
namespace gcTest

{

     class gcDemo

     {

         private static void GenerationDemo()

         {

              // Let's see how many generations the GCH supports (we know it's 2)

              Console.WriteLine("Maximum GC generations: {0}", GC.MaxGeneration);

 

              // Create a new BaseObj in the heap

              GenObj obj = new GenObj("Generation");

 

              // Since this object is newly created, it should be in generation 0

              obj.DisplayGeneration();    // Displays 0

 

              for(int i = 1; i <= GC.MaxGeneration; i++)

              {

                   // Performing a garbage collection promotes the object's generation

                   GC.Collect();

                   obj.DisplayGeneration();    // Displays i

              }

 

              obj = null;         // Destroy the strong reference to this object

 

              for(int i = 0; i <= GC.MaxGeneration; i++)

              {

                   GC.Collect(i);                  

                   GC.WaitForPendingFinalizers();

                   //suspend this thread until the freachable queue of

                   //the i generation has been emptied

                   //only when i = GC.MaxGeneration, this finalization method

                   //of obj will be performed

              }

 

              Console.WriteLine("Demo stop: Understanding Generations.");

              //total gc times

              //generation 0 : 5 times

              //generation 1 : 4 times

              //generation 2 : 3 times

         }

 

         public static void Main()

         {

              GenerationDemo();

         }

     }

 

     class GenObj

     {

         private string objName;

 

         public GenObj(string name)

         {

              this.objName = name;

         }


         public void DisplayGeneration()

         {

              Console.WriteLine("I am in Generation {0}", GC.GetGeneration(this));

         }

     };

}
View Code

相关文章: