.NET 垃圾收集器基础知识

原文 标签 .net memory memory-management memory-leaks garbage-collection

这个问题在这里已经有了答案:





Understanding garbage collection in .NET

(2 个回答)


6年前关闭。




如果这个问题的答案是微不足道的,我很抱歉。但我自己仍然无法弄清楚这一点。

.NET 中的垃圾收集器如何识别堆上的哪些对象是垃圾,哪些对象不是?

假设一个 .NET 应用程序正在运行,并且在某个时间点发生垃圾收集(为了简单起见,让我们忽略生成和完成队列)。

现在应用程序可能有:

  • 堆栈变量指向堆上的对象。
  • 包含堆上对象地址的寄存器。
  • 指向堆上对象的静态变量。

  • 这就是我假设 GC 的工作方式。
  • 它取消引用每个这样的地址并最终到达堆上的对象。
  • 它将对象标记为非垃圾(通过使用同步块(synchronized block)索引),因为某些变量仍指向它。
  • 它对所有地址执行此操作(在大多数文章中出于某种原因称为根)
  • 现在,由于 .NET 运行时有关于每个对象的 TYPE 的信息,它可以计算每个对象的大小,从而计算它占用的堆内存块。对于所有标记的对象,它使内存块保持原样。
  • 其余的内存被释放、压缩,如果需要,其他对象被重新定位(并且它们的地址被更新)。

  • 我的理解正确吗?

    最佳答案

    在某些情况下你是对的。 GC 悲观地查看堆 - 即它开始假设所有内容(在第 0 代中)都将被 GC。

    它实际上通过称为“标记”的第一次扫描遍历堆上的所有内容,其中检查是否有任何东西引用它。由于它们都是引用类型,而一些引用其他类型,它将递归地导航引用。别担心 - 有逻辑不进入无限循环!

    如果它发现一个对象没有被引用,它会首先通过在对象内设置一个称为同步块(synchronized block)索引的标志来标记它。

    在遍历堆上的每个对象之后,它将开始一个称为“压缩”的过程,即当它将所有剩余的对象转移到同一内存区域中时,上面的内存是空的。它将同一代的对象保持在一起,因为它们在统计上更有可能同时被取消引用。

    因此,这将减少所需的内存。

    垃圾收集不一定会加速您的程序,但确实允许它重新使用未使用对象占用的空间。

    关于这个主题有很多很多文章。我个人喜欢 Jeffrey Richter 的“CLR via C#”,他给出了一个关于它如何工作的精彩章节。

    关于.NET 垃圾收集器基础知识,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1090451/

    相关文章:

    c++ - C++ 中的快速内存访问?

    .net - 反序列化和空引用最佳实践 - 设置为空还是忽略?

    .net - 如何在运行时检测 .NET 4.5 版当前正在运行您的代码?

    c# - 在 C# 中释放内存的正确方法是什么

    python - 如何确定 Python 中对象的大小?

    memory - Tcl 可变大小限制

    c# - 在任何应用程序中使用持久层有什么用?

    c# - .NET HttpClient - 取消 CancellationToken 不取消请求

    c - 填写作为指针传递的 vector (C)

    python - 在不实例化任何对象的情况下使用实例方法可能很危险或有用?