Хорошо, я понимаю, что этот вопрос может показаться странным, но я только что заметил то, что действительно озадачило меня... Посмотрите на этот код:
static void TestGC()
{
object o1 = new Object();
object o2 = new Object();
WeakReference w1 = new WeakReference(o1);
WeakReference w2 = new WeakReference(o2);
GC.Collect();
Console.WriteLine("o1 is alive: {0}", w1.IsAlive);
Console.WriteLine("o2 is alive: {0}", w2.IsAlive);
}
Так как o1
и o2
все еще находятся в области видимости, когда происходит сбор мусора, я ожидал следующий вывод:
o1 жив: True
o2 жив: True
Но вместо этого вот что я получил:
o1 жив: False
o2 жив: False
ПРИМЕЧАНИЕ: это происходит только тогда, когда код компилируется в режиме деблокирования и запускается за пределами отладчика
Мое предположение заключается в том, что GC обнаруживает, что o1
и o2
больше не будут использоваться до того, как они выйдут из области действия, и собирают их раньше. Чтобы проверить эту гипотезу, я добавил следующую строку в конце метода TestGC
:
string s = o2.ToString();
И я получил следующий вывод:
o1 жив: False
o2 жив: True
Итак, в этом случае o2
не собирается.
Может ли кто-то пролить свет на то, что происходит? Связано ли это с оптимизацией JIT? Что происходит точно?