Казалось бы, простой вопрос: может ли среда CLR вызвать финализатор объекта, когда экземплярный метод не завершил свое исполнение?
Другими словами, возможно ли в следующем случае увидеть «Finalizing instance.» до «Finished doing something.»?
internal class GcIsWeird
{
~GcIsWeird()
{
Console.WriteLine("Finalizing instance.");
}
public int data = 42;
public void DoSomething()
{
Console.WriteLine("Doing something. The answer is ... " + data);
// Some other code...
Console.WriteLine("Finished doing something.");
}
}
static void SomeWeirdAndVeryLongRunningStaticMethod()
{
var heavyWeightInstance = new int[42_000_000];
// The very last reference to 'heavyWeightInstance'
Console.WriteLine(heavyWeightInstance.Length);
for (int i = 0; i < 10_000; i++)
{
// Doing some useful stuff.
Thread.Sleep(42);
}
}
class Program
{
internal class GcIsWeird
{
~GcIsWeird()
{
Console.WriteLine("Finalizing instance.");
}
public int data = 42;
public void DoSomething()
{
Console.WriteLine("Doing something. The answer is ... " + data);
CheckReachability(this);
Console.WriteLine("Finished doing something.");
}
}
static void CheckReachability(object d)
{
var weakRef = new WeakReference(d);
Console.WriteLine("Calling GC.Collect...");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
string message = weakRef.IsAlive ? "alive" : "dead";
Console.WriteLine("Object is " + message);
}
static void Main(string[] args)
{
new GcIsWeird().DoSomething();
}
}
Doing something. The answer is ... 42
Calling GC.Collect...
Finalizing instance.
Object is dead
Finished doing something
*************** After end code gen, before unwindEmit()
IN0002: 000012 call CORINFO_HELP_NEWSFAST
IN0003: 000017 mov rcx, 0x1FE90003070
// Console.WriteLine("Doing something. The answer is ... " + data);
IN0004: 000021 mov rcx, gword ptr [rcx]
IN0005: 000024 mov edx, dword ptr [rsi+8]
IN0006: 000027 mov dword ptr [rax+8], edx
IN0007: 00002A mov rdx, rax
IN0008: 00002D call System.String:Concat(ref,ref):ref
IN0009: 000032 mov rcx, rax
IN000a: 000035 call System.Console:WriteLine(ref)
// CheckReachability(this);
<b>IN000b: 00003A mov rcx, rsi</b>
// После этого момента указатель «this» доступен для GC
IN000c: 00003D call Reachability.Program:CheckReachability(ref)
// Console.WriteLine
IN000d: 000042 mov rcx, 0x1FE90003078
IN000e: 00004C mov rcx, gword ptr [rcx]
IN000f: 00004F mov rax, 0x7FFB6C6B0160
*************** Variable debug info
2 vars
0( UNKNOWN) : From 00000000h to 00000008h, in rcx
<b>0( UNKNOWN) : From 00000008h to 0000003Ah, in rsi</b>
*************** In gcInfoBlockHdrSave()
<b>Register slot id for reg rsi = 0.</b>
Set state of slot 0 at instr offset 0x12 to Live.
Set state of slot 0 at instr offset 0x17 to Dead.
Set state of slot 0 at instr offset 0x2d to Live.
Set state of slot 0 at instr offset 0x32 to Dead.
Set state of slot 0 at instr offset 0x35 to Live.
<b>Set state of slot 0 at instr offset 0x3a to Dead.</b>
К сожалению, не доступен сервер mySQL