垃圾收集机制如何运作?

时间:2009-04-21 20:07:14

标签: memory-management garbage-collection

在一个非专业术语中,垃圾收集机制如何运作?

如何识别对象可用于垃圾回收?

此外,Reference Counting, Mark and Sweep, Copying, Train在GC算法中意味着什么?

5 个答案:

答案 0 :(得分:34)

当您使用垃圾收集语言时,您将无法直接访问内存。相反,您可以在该数据之上访问某些抽象。正确抽象出来的一件事是数据块内存中的实际位置,以及指向其他数据块的指针。当垃圾收集器运行时(偶尔会发生这种情况),它将检查您是否仍然保持对它为您分配的每个内存块的引用。如果你不这样做,它将释放那段记忆。

不同类型的垃圾收集器之间的主要区别在于它们的效率以及它们可以处理的分配方案的任何限制。

最简单的是正确引用计数。当您创建对象的引用时,该对象上的内部计数器会递增,当您有可能引用它或它不再在作用域中时,(前)目标对象上的计数器会递减。当此计数器达到零时,该对象将不再被引用,并且可以被释放。

引用计数垃圾收集器的问题是它们无法处理循环数据。如果对象A具有对对象B的引用,并且对对象A具有一些(直接或间接)引用,则它们永远不会被释放,即使链中没有任何对象被引用到链外(因此也不是)该计划完全可以访问。)

另一方面,标记和扫描算法可以处理这个问题。标记和扫描算法通过定期停止程序的执行来工作,将程序分配的每个项目标记为不可达。然后程序运行程序具有的所有变量,并标记它们指向的可达性。如果这些分配中的任何一个包含对程序中其他数据的引用,则该数据同样被标记为可达等等。

这是算法的标记部分。此时,程序可以访问的所有,无论多么间接,都标记为可访问,程序无法访问的所有内容都标记为无法访问。垃圾收集器现在可以安全地回收与标记为无法访问的对象关联的内存。

标记和扫描算法的问题在于效率不高 - 必须停止整个程序才能运行它,并且很多对象引用都不会改变。

为了改进这一点,可以使用所谓的“世代垃圾收集”来扩展标记和扫描算法。在此模式下,系统中已存在一定数量垃圾收集的对象将被提升为旧代,而这些对象通常不会被检查。

这提高了效率,因为对象倾向于年轻(想到一个字符串在循环内被改变,导致可能有几百个循环的生命周期)或活得很长(用于表示应用程序主窗口的对象) ,或servlet的数据库连接。)

可以在维基百科上找到更详细的信息。

根据评论添加:

使用标记和扫描算法(以及除引用计数之外的任何其他垃圾收集算法),垃圾收集在程序的上下文中运行,因为它必须能够访问你的程序无法直接访问的东西。因此,说垃圾收集器在堆栈上运行是不正确的。

答案 1 :(得分:4)

  • 引用计数 - 每个对象都有 计数,当时增加 有人参考了 对象,当有人减少 发布参考。当引用计数变为零时,将删除该对象。 COM使用 这种方法。
  • 标记和扫描 - 如果正在使用,每个对象都有一个标记。从对象图的根(全局变量,堆栈上的本地等)开始,每个引用的对象都会设置其标志,依此类推。最后,删除图表中未引用的所有对象。

slidedeck中描述了CLR的垃圾收集器。幻灯片15上的“根”是首先进入图表的对象的来源。它们的成员字段等用于查找图中的其他对象。

Wikipedia更详细地介绍了其中的几种方法。

答案 2 :(得分:3)

垃圾收集只是知道程序中是否有将来需要变量,如果没有,请收集并删除它们。

重点在于 Garbage 这个词,在你家里完全用完的东西被扔进了垃圾桶里,垃圾人把它捡起去把它带走给你房子垃圾桶留出更多空间。

GC FAQ

详细讨论了参考计数,标记和扫描,复制,训练等。

答案 3 :(得分:0)

它完成的一般方法是在后台跟踪对象的引用数量,当该数字变为零时,该对象是SUBJECT TO垃圾收集,但GC不会启动它是明确需要的,因为它是一项昂贵的操作。它启动时会发生的事情是GC通过内存的管理区域并找到没有引用的每个对象。 gc通过首先调用它们的析构函数来删除这些对象,允许它们自己清理,然后释放内存。通常,GC会通过将每个幸存对象移动到一个内存区域来压缩托管内存区域,从而允许进行更多分配。

就像我说的这是我所知道的一种方法,并且在这方面已经进行了大量的研究。

答案 4 :(得分:0)

Garbage collection是一个很大的主题,有很多方法可以实现它。

但是对于最常见的简而言之,垃圾收集器会记录对通过new运算符创建的任何内容的所有引用,即使该运算符的使用对您是隐藏的(例如,在{{ 1}}方法)。每次添加对象的新引用时,都会确定该引用的 root 并将其添加到列表中(如果需要)。只要超出范围,就会删除引用。

当没有对象的更多引用时,它可以(不是“将”)被收集。为了提高性能并确保正确完成必要的清理,集合将同时为多个对象进行批处理,并在多代中进行。