1

我在 Windows x64 上运行的 .NET Core 2.1 应用程序分配大型结构数组,每个结构在字段中保存一个类。数组最终位于大对象堆上,因此直到完整(第 2 代)GC 才会收集它们。这是意料之中的。让我有点吃惊的是,结构引用的类似乎在第 2 代 GC 之前也不会被 GC。这是预期的行为吗?

如果我也有一个大的 HashSet,就会发生类似的事情,因为 HashSet 在内部保留了一个 HashSet.Slot 数组 - 一个结构。

一些重现问题的代码:

    class MyClass
    {
        public long Value;

        ~MyClass()
        {
            if (Value < 10)
            {
                Console.WriteLine("MyClass finalizer " + Value);
            }
        }
    }

    struct TheEntry
    {
        public MyClass TheClass;
    }

    class Program
    {
        static void Main(string[] args)
        {
            var wr = AllocateSomeStuff();
            Console.WriteLine("Before GC MyClass is in gen " + GC.GetGeneration(wr));

            GC.Collect(1);
            Console.WriteLine("GC done");
            GC.WaitForPendingFinalizers();
            Console.WriteLine("Finalizers done");
            Console.WriteLine("After GC MyClass is in gen " + GC.GetGeneration(wr));
        }

        private static WeakReference<MyClass> AllocateSomeStuff()
        {
            var array = new TheEntry[11000];

            for (int i = 0; i < array.Length; ++i)
            {
                array[i].TheClass = new MyClass { Value = i };
            }

            return new WeakReference<MyClass>(array[0].TheClass);
        }
    }

当我在 64 位系统上使用包含 11,000 个元素的数组运行此程序时(因此它超过了 LOH 的 85KB 阈值),MyClass 的终结器不会运行。输出:

Before GC MyClass is in gen 0
GC done
Finalizers done
After GC MyClass is in gen 1

他们运行 10,000 个元素。我想我希望运行时 GC MyClass 因为它无法访问,即使它仍然被另一个无法访问的对象引用。这是它应该如何工作的吗?

4

0 回答 0