垃圾收集失败的可能原因

时间:2016-12-23 10:21:12

标签: c# .net garbage-collection

这是我写的一些简单的测试代码:

class Simple
{

}

class Finalizing
{
    public static volatile bool AllowFinalization = false;
    ~Finalizing()
    {
        Debug.WriteLine("Finalizer starting.");
        while (!AllowFinalization) ;
        Debug.WriteLine("Finalizer finishing.");
    }
}

static class Program
{
    static string CheckAlive(WeakReference wr)
    {
        if (!wr.IsAlive)
            return "dead";

        try
        {
            return "alive in gen" + GC.GetGeneration(wr);
        }
        catch (ArgumentException)
        {
            return "dead";
        }
    }

    static void Main(string[] args)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        var simple = new WeakReference(new Simple());
        var finalizingShort = new WeakReference(new Finalizing());
        var finalizingLong = new WeakReference(new Finalizing(), true);
        var suppressedShort = new WeakReference(new Finalizing());
        GC.SuppressFinalize(suppressedShort.Target);
        var suppressedLong = new WeakReference(new Finalizing(), true);
        GC.SuppressFinalize(suppressedLong.Target);

        Debug.WriteLine("Simple " + CheckAlive(simple));
        Debug.WriteLine("FinalizingShort" + CheckAlive(finalizingShort));
        Debug.WriteLine("FinalizingLong " + CheckAlive(finalizingLong));
        Debug.WriteLine("SuppressedShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("SuppressedLong " + CheckAlive(finalizingLong));

        Debug.WriteLine("");
        Debug.WriteLine("Collecting...");
        GC.Collect();
        Debug.WriteLine("Simple " + CheckAlive(simple));
        Debug.WriteLine("FinalizingShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("FinalizingLong " + CheckAlive(finalizingLong));
        Debug.WriteLine("SuppressedShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("SuppressedLong " + CheckAlive(finalizingLong));

        Debug.WriteLine("");
        Debug.WriteLine("Waiting for finalizers...");
        Finalizing.AllowFinalization = true;
        GC.WaitForPendingFinalizers();
        Debug.WriteLine("Simple " + CheckAlive(simple));
        Debug.WriteLine("FinalizingShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("FinalizingLong " + CheckAlive(finalizingLong));
        Debug.WriteLine("SuppressedShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("SuppressedLong " + CheckAlive(finalizingLong));

        Debug.WriteLine("");
        Debug.WriteLine("Recollecting...");
        GC.Collect();
        Debug.WriteLine("Simple " + CheckAlive(simple));
        Debug.WriteLine("FinalizingShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("FinalizingLong " + CheckAlive(finalizingLong));
        Debug.WriteLine("SuppressedShort " + CheckAlive(finalizingShort));
        Debug.WriteLine("SuppressedLong " + CheckAlive(finalizingLong));
    }
}

基本上,它对不同类型的对象进行了一些不同类型的弱引用,并检查这些对象在某些垃圾收集事件之后发生了什么。输出是预期的,如下所示:

Simple alive in gen0
FinalizingShortalive in gen0
FinalizingLong alive in gen0
SuppressedShort alive in gen0
SuppressedLong alive in gen0

Collecting...
Simple dead
FinalizingShort dead
FinalizingLong alive in gen1
Finalizer starting.
SuppressedShort dead
SuppressedLong alive in gen1

Waiting for finalizers...
Finalizer finishing.
Finalizer starting.
Finalizer finishing.
Simple dead
FinalizingShort dead
FinalizingLong alive in gen1
SuppressedShort dead
SuppressedLong alive in gen1

Recollecting...
Simple dead
FinalizingShort dead
FinalizingLong dead
SuppressedShort dead
SuppressedLong dead

有趣的是,所有具有终结器的对象,甚至是被压缩的对象,都能在一个集合中存活下来。但这不是这个问题的关键所在。

在程序中发生任何其他操作之前,我将相同的代码复制粘贴到我的Windows窗体项目的主要方法的开头。当然,我期待相同的结果,但这是我得到的输出:

Simple alive in gen0
FinalizingShortalive in gen0
FinalizingLong alive in gen0
SuppressedShort alive in gen0
SuppressedLong alive in gen0

Collecting...
Simple alive in gen1
FinalizingShort alive in gen1
FinalizingLong alive in gen1
SuppressedShort alive in gen1
SuppressedLong alive in gen1

Waiting for finalizers...
Simple alive in gen1
FinalizingShort alive in gen1
FinalizingLong alive in gen1
SuppressedShort alive in gen1
SuppressedLong alive in gen1

Recollecting...
Simple alive in gen2
FinalizingShort alive in gen2
FinalizingLong alive in gen2
SuppressedShort alive in gen2
SuppressedLong alive in gen2

换句话说,即使我明确地运行GC.Collect(),也不会收集对象。有没有人有关于如何调试这个的任何提示?什么可能导致它?请记住,这是引用其他程序集的代码,因此它们可能会以某种方式搞乱我的垃圾收集?

0 个答案:

没有答案