【问题标题】:when .net garbage collector doesn't compact gc heap?当 .net 垃圾收集器不压缩 gc 堆时?
【发布时间】:2012-02-07 09:24:39
【问题描述】:

我运行以下代码

        StringBuilder sb = new StringBuilder();
        Stack  stack = new Stack();
        SynchronizationContext sc = new SynchronizationContext();

        GC.Collect();
        Console.WriteLine("GC. First Execution.");

        stack = null;

        GC.Collect();
        Console.WriteLine("GC. Second Execution.");

        GC.Collect();
        Console.WriteLine("GC. Third Execution.");

在使用 SOS 调试此代码时,我看到在首次执行 GC 之后,地址如下:

!dso
...
0239b5f8 System.Threading.SynchronizationContext
0239b5a8 System.Collections.Stack
0239b560 System.Text.StringBuilder
...

Second Execution 后堆中没有“​​stack”对象,但其他地址为:

!dso
...
0239b5f8 System.Threading.SynchronizationContext
0239b560 System.Text.StringBuilder
...

所以“堆栈”对象已被收集,但 sc (SynchronizationContext) 对象并未重新定位到要压缩的内存中。我们的内存有缺口

!do 0239b5a8
Free Object
Size:        80(0x50) bytes

第三次执行后情况相同。

为什么会这样?为什么在这种情况下不执行“紧凑”操作?

谢谢。

【问题讨论】:

  • 有趣。我猜想同步上下文包含一堆与单例模式相关的静态不可重定位字段。这可能是需要从另一个线程直接访问对象的情况。
  • 谢谢。您是指“固定”对象吗?
  • 我尝试对 SynchronizationContext 使用自定义 Foo 对象 - sutionations 是相同的。内存中的对象 Foo 不会被替换为压缩的男性堆。
  • 更大的问题是为什么 all 对象没有被收集。不要测试你在 Debug 配置中编译的代码,你不会得到有代表性的结果。
  • 谢谢各位。我在微软官方文档中找到了答案(抱歉没有链接,它是印刷文档)。将对象标记为未使用(待删除的候选对象)后,GC 执行计划阶段。 “计划:.NET 垃圾收集器为正在收集的每一代创建一个代预算,然后确定由于 GC 将在托管堆中发生的碎片量,以决定压缩是否有效。”但是我一直认为compaction总是由GC来完成的。我的知识存在差距,而不是 GC Heap )))

标签: .net clr garbage


【解决方案1】:

GC 懒得提高效率。在需要之前,它实际上不会免费或如您所说的“紧凑”。该对象已移至处置队列。

您可以等待数天而看不到它清理干净。它会在资源不足且需要时进行清理。

【讨论】:

  • 罗伯,谢谢。但正如我们所见,“堆栈”对象是免费的(已清理)。问题是,为什么 'sc' 对象没有占用他的地址 0239b5a8
  • 您已将“堆栈”对象设置为“空”对象。它实际上不是 null,但现在是对 null 对象的引用。因此,标识符“stack”现在引用了一个名为 null 的系统对象。
猜你喜欢
  • 1970-01-01
  • 2011-08-31
  • 2014-08-26
  • 2023-03-30
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多