我在 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 因为它无法访问,即使它仍然被另一个无法访问的对象引用。这是它应该如何工作的吗?