c# - 托管堆 OutOfMemory

标签 c# .net garbage-collection out-of-memory

编辑:我将其重新表述为问题并将答案移至答案部分...

在一个相对复杂的多线程 .NET 应用程序中,我遇到了 OutOfMemoryException,即使在我认为没有理由的情况下也是如此。

情况:

  • 应用程序是 32 位的。
  • 该应用程序创建了许多(数千个)被认为很小(小于大约 85kB)的短期对象。
  • 此外,它还会创建一些(数百个)被认为是大型(大于约 85kb)的短期对象。这意味着这些对象是在 LOH(大对象堆)中分配的。
  • 这些对象的两个类都定义了终结器 (~MyFinalizer(){...})。

症状:

  • OutOfMemoryException
  • 通过内存分析器查看应用程序,有数千个小对象符合收集条件,但未被收集,因此阻塞了大量内存。

问题:

  • 为什么应用会耗尽整个堆?
  • 为什么内存中仍然存在大量“死”对象?

最佳答案

经过深入调查,我找到了原因。由于花费了一些时间,我想让其他遇到同样问题的人也能轻松一些。

原因:

  • 应用只有大约 2GB 的虚拟地址空间。
  • LOH 在设计上并未压缩,因此可能会很快碎片化,但对于上述大对象的数量,这应该不是任何问题。
  • 由于垃圾收集器的设计,如果有定义终结器的对象(即使是空的),它会被视为 Gen2 对象并放入 GC 的终结队列中。这意味着,在完成之前(调用 MyFinalizer)它只会阻塞内存。在上述应用的情况下,运行终结器的 GC 线程没有机会尽快完成其工作,因此堆已耗尽。

解决方案:

不要对此类“动态”对象(高容量、短生命周期)使用终结器,以其他方式解决终结代码...

非常有用的资源:

关于c# - 托管堆 OutOfMemory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25033335/

相关文章:

c# - Decimal.Parse 和不正确的字符串格式错误

c# - 以最佳性能将数据插入 SQL Server

c# - 如何在不知道下一个值的数据类型的情况下读取二进制文件?

java - 如何在运行时查找一个对象是否引用另一个对象

garbage-collection - 为什么垃圾收集器在分配之前要等待?

c# - 从枚举列表生成 Linq 或子句

c# - Identity Server 3 访问 token 验证库无法验证从 Identity Server 4 生成的 token

c# - 如果我的函数在处理时失败,System.MessageQueue (MSMQ) 消息是否会丢失?

c# - OracleDataReader 出错。错误 : Invalid operation. 连接已关闭

flash - 从浏览器卸载时清理 as3 flash 应用程序