【发布时间】:2012-04-04 05:55:02
【问题描述】:
垃圾收集器如何知道对象和变量超出范围,以便它们可以被垃圾收集器收集?
【问题讨论】:
-
你看过 MSDN 吗? msdn.microsoft.com/en-us/library/ee787088.aspx
标签: asp.net .net c#-4.0 garbage-collection
垃圾收集器如何知道对象和变量超出范围,以便它们可以被垃圾收集器收集?
【问题讨论】:
标签: asp.net .net c#-4.0 garbage-collection
简而言之:每个应用程序都有一组根。根标识存储位置,这些位置引用托管堆上的对象或设置为 null 的对象。
当垃圾收集器开始运行时,它会假设堆中的所有对象都是垃圾。
垃圾收集器开始遍历根并构建从根可到达的所有对象的图。
所有不可达的对象都被删除(内存被释放)
这取自http://msdn.microsoft.com/en-us/magazine/bb985010.aspx - 关于垃圾收集的好文章。对你来说“有趣”的部分是“垃圾收集算法”。这不是一个很长的部分
【讨论】:
如果不参考 Raymond Chen 的一系列优秀博文,对 .NET 中的垃圾收集的讨论是不完整的:
这是该系列第一篇文章的引述:
当你问别人什么是垃圾回收时,你得到的答案可能类似于“垃圾回收是指操作环境自动回收程序不再使用的内存。它会这样做通过从根开始跟踪内存来识别哪些对象是可访问的。”
这个描述混淆了机制和目标。就像说消防员的工作是“开红色卡车喷水”一样。这是对消防员工作的描述,但它忽略了工作的重点(即扑灭火灾,更一般地说,消防安全)。
以下是他展示的一些有趣的观点:
一个正确编写的程序不能假设终结器会运行。
代码块中的对象可以在其调用的函数执行期间有资格被收集。
方法的参数可以在方法仍在执行时被收集。
一个奇怪的现实类比:垃圾收集器可以在潜水员最后一次触摸你的跳水板时收集它——即使潜水员还在空中!
最简洁的:
不要将 GC 视为跟踪根。将 GC 视为删除您不再使用的东西。
【讨论】:
垃圾收集器 (GC) 是 .NET 框架的一部分,由 公共语言运行时 (CLR) 初始化以管理分配和释放应用程序中的内存。
垃圾收集器的类型
垃圾收集器可以在多种场景中工作。 CLR 提供以下类型的垃圾回收:
并发垃圾回收 并发垃圾收集允许用户线程在第 2 代垃圾收集的大部分时间运行。只要托管堆中仍有用于新分配的空闲空间,就允许用户线程运行并创建新对象。
非并发垃圾回收 非并发垃圾回收会在整个垃圾回收期间暂停所有非垃圾回收线程,从而在这段时间内有效地暂停应用程序。
后台垃圾回收 后台垃圾回收是并发垃圾回收的替代品。它类似于并发垃圾收集,但允许第 0 代和第 1 代垃圾收集中断正在进行的第 2 代垃圾收集并暂时阻止程序执行。在第 0 代和第 1 代垃圾收集完成后,程序执行和第 2 代垃圾收集都将继续进行。这甚至进一步缩短了程序执行因垃圾回收而暂停的时间。
内存和托管堆 一旦垃圾收集器被公共语言运行时 (CLR) 初始化,它就会分配一段称为托管堆的内存段,该内存段与操作系统中的本地堆相反,用于存储和管理对象。 p>
对于每个托管进程,垃圾收集器使用 Windows VirtualAlloc 函数在托管堆中保留一段内存。 (它使用 Windows VirtualFree 功能将段释放回操作系统)。进程中的所有线程都为同一个堆上的对象分配内存。
需要考虑的重要一点是,每个分配段的大小是特定于实现的,并且随时可能发生变化。
世代
存储在托管堆中的对象根据它们的年龄被组织成几代。垃圾回收主要发生在回收短寿命对象时,这些对象通常只占用堆的一小部分。
当垃圾收集器检测到某一代的存活率很高时,它会增加该代的分配阈值。
垃圾收集器阶段
集合由以下条件之一触发:
系统的物理内存不足。这由任一检测到 来自操作系统的内存不足通知或内存不足,如 主持人。
托管堆上分配的对象使用的内存 超过可接受的阈值。这个阈值是连续的 在进程运行时进行调整。
调用 GC.Collect 方法。在几乎所有情况下,您都没有 调用这个方法,因为垃圾收集器一直在运行。
此时垃圾收集器通过抛出以下阶段:
标记阶段:GC 创建所有活动对象的列表(所有
不在列表中的对象可能会被删除)by
使用以下信息来确定对象是否是
生活与否:
重定位阶段:所有活动对象列表中的所有对象的引用都会在重定位阶段更新,以便它们指向对象将要存放的新位置在压实阶段被重新定位。 压缩阶段:回收死对象占用的空间并压缩幸存对象。压缩阶段将在垃圾收集中幸存下来的对象移向段的较旧端。堆在压缩阶段被压缩,因为死对象占用的空间被释放并且剩余的活动对象被移动。垃圾回收后剩余的所有活动对象都按其原始顺序移向堆内存的旧端
资源
官方文档:https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
【讨论】:
请转至http://msdn.microsoft.com/en-us/magazine/bb985010.aspx。 正如它所说的
垃圾收集器检查堆中是否有任何对象不再被应用程序使用。如果存在此类对象,则可以回收这些对象使用的内存。
【讨论】: