2

我正在玩.Net GC(仅用于教育目的),我对它的行为感到惊讶。

我已经建立了一个基本程序:

  • 创建一个对象
  • 显示其单个字段的地址及其当前代
  • 运行一个集合
  • 第二次显示地址和代
  • 运行第二个集合
  • 第三次显示地址和代

我希望地址和代每次都会改变,因为对象从一代提升到下一代,并从一个内存区域移动到下一个。

这对于在每个集合中递增但字段地址始终相同的生成是正确的。

这是IL代码:

.assembly GCGenerationsSample { }
.assembly extern mscorlib { }

.class A extends [mscorlib]System.Object
{
    .field int32 n;

    .method instance void .ctor()
    {
        ldarg.0
        call instance void [mscorlib]System.Object::.ctor()
        ret
    }
}

.method static void Main()
{
    .entrypoint

    .locals (class A)

    newobj instance void A::.ctor()
    stloc.0

    // Display address of field "n"
    ldloc.0
    ldflda int32 A::n
    call void [mscorlib]System.Console::WriteLine(int32)

    // Display generation of object
    ldloc.0
    call int32 [mscorlib]System.GC::GetGeneration(object)
    call void [mscorlib]System.Console::WriteLine(int32)

    // Run a full GC
    call void [mscorlib]System.GC::Collect()

    // Display address of field "n"
    ldloc.0
    ldflda int32 A::n
    call void [mscorlib]System.Console::WriteLine(int32)

    // Display generation of object
    ldloc.0
    call int32 [mscorlib]System.GC::GetGeneration(object)
    call void [mscorlib]System.Console::WriteLine(int32)

    // Run a full GC
    call void [mscorlib]System.GC::Collect()

    // Display address of field "n"
    ldloc.0
    ldflda int32 A::n
    call void [mscorlib]System.Console::WriteLine(int32)

    // Display generation of object
    ldloc.0
    call int32 [mscorlib]System.GC::GetGeneration(object)
    call void [mscorlib]System.Console::WriteLine(int32)

    ret
}

和输出:

39070896
0
39070896
1
39070896
2

要么我错过了什么,要么做了一些愚蠢的事情,或者两者兼而有之(很可能)。

任何想法都非常受欢迎。

4

1 回答 1

1

为了让它移动,您需要在被收集的幸存几代的对象之前分配一些东西,以便幸存的对象有一些空间可以压缩。

您的对象始终位于堆的开头,因此它不需要移动到任何地方。

于 2014-01-03T23:29:14.947 回答