我知道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
答案 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代中分配。