垃圾收集如何决定变量的生成

时间:2017-01-07 13:23:54

标签: c# memory-management garbage-collection

我知道GC有3(0,1,2)代,但我想知道GC如何决定变量的生成?

我认为所有变量都会进入第0代,经过一段时间后会转移到第1代和第2代。对于GC来说,决定生成是否重要?

PROGRAM1:

private static void Main(string[] args)
{
        int a = 0;
        string name = "Test";
        var byteArray = new byte[10];
        byteArray[4] = 4;

        Console.WriteLine($"Generation of array {GC.GetGeneration(byteArray)}");
        Console.WriteLine($"Generation of local int variable {GC.GetGeneration(a)}");
        Console.WriteLine($"Generation of local string variable {GC.GetGeneration(name)}");
}

结果

Generation of array 0
Generation of local int variable 0
Generation of local string variable 0

Program2中:

private static void Main(string[] args)
{
        int a = 0;
        string name = "Test";
        var byteArray = new byte[100000000];
        byteArray[4] = 4;

        Console.WriteLine($"Generation of array {GC.GetGeneration(byteArray)}");
        Console.WriteLine($"Generation of local int variable {GC.GetGeneration(a)}");
        Console.WriteLine($"Generation of local string variable {GC.GetGeneration(name)}");

}

结果

Generation of array 2
Generation of local int variable 0
Generation of local string variable 0

2 个答案:

答案 0 :(得分:6)

  

我想知道GC如何决定变量的生成?

变量首先不是GC。 引用类型的对象是GC' d。那些对象包含变量,但它是收集的对象

  

我认为所有变量都进入第0代,经过一段时间后转移到第1代和第2代。

没有。不要在变量方面思考。从对象的角度思考。新分配的对象进入gen0。如果该对象在集合中存活,则将其移至gen1。如果它在另一个集合中存活,它将移至gen2。

所以现在你知道为什么在包含int的局部变量上调用GetGeneration总是返回零。这不是因为本地在某种程度上与gen0神奇地联系在一起。 local不是引用类型的对象,也不是它的值!

当你将int传递给GetGeneration时,int被装入一个对象;该对象是新分配的,因此它在第0代。这不会告诉您关于变量的任何信息。如果将任何(非null)值类型传递给触发分配的GetGeneration,显然该分配是gen0。

同样,您的问题表明您认为GC正在查看变量的生命周期。 不是。它正在查看引用类型对象的生命周期。

  

GC决定生成是否重要?

是。例如,非常大的数组是从特殊的"大对象堆中分配的。通过"非常大",我们的意思是基本上任何大约85KB或更大的对象。大对象堆是(1)未压缩,(2)仅在常规堆执行gen2集合时收集。

答案 1 :(得分:1)

第0代和第1代需要很小,以便快速收集它们。为了保持它们的小,非常大的对象直接在第2代中分配。

相关问题