2009-04-21 54 views
21

在非专业术语中垃圾收集机制是如何工作的?垃圾收集机制如何工作?

如何确定一个对象用于垃圾回收?

另外,在GC算法中,Reference Counting, Mark and Sweep, Copying, Train是什么意思?

+4

没有......没有。可能它看起来就像我说的那样。任何方式 – 2009-04-21 20:16:00

+1

我推荐阅读相当好的,34页插图的论文,[* Uniprocessor Garbage Collection Techniques *,Paul R.Wilson(1992)](http://www.cse.nd.edu/~dthain /courses/cse40243/spring2006/gc-survey.pdf),它解释了基本垃圾收集技术(引用计数,标记和扫描,标记压缩,增量,代数)背后的概念。 – stakx 2012-06-16 11:36:16

回答

29

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

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

最简单的就是正确引用计数。当您创建对象的引用时,该对象上的内部计数器会递增,如果偶然引用或它不在范围内,则(之前)目标对象上的计数器递减。当这个计数器达到零时,该对象不再被引用并且可以被释放。

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

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

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

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

为了改善这一点,标记和扫描算法可以扩展为所谓的“分代垃圾收集”。在这种模式下,已经在系统中存在一些垃圾收集数量的对象被提升到旧一代,而不是经常检查。

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

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

添加基于评论:

与标记和清除算法(以及除了引用计数的任何其他垃圾收集算法)垃圾回收做在程序的情况下运行,因为它必须能够访问您的程序无法直接访问的内容。因此,说垃圾收集器在堆栈上运行是不正确的。

3

垃圾收集只是简单地知道您的程序中是否有将来对变量的需求,如果没有,则收集并删除它们。

重点在于这个词垃圾,你的房子里被完全使用的东西被扔在垃圾桶里,垃圾人通过捡起来把它拿走,把它拿走给你更多的空间在你家垃圾桶里。

引用计数,标记和清除,复制,火车等的在良好的细节在GC FAQ

4
  • 引用计数讨论 - 每个对象具有 ,其被递增时 有人需要到 的引用的计数对象,并在有人 释放引用时递减。当引用计数变为零时,该对象被删除。 COM使用 这种方法。
  • 标记和扫描 - 如果正在使用每个对象都有一个标记。从对象图的根部开始(全局变量,堆栈上的本地等),每个引用的对象都会设置标志,依此类推。最后,删除图中未引用的所有对象。

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

Wikipedia以更多更好的细节描述了其中的几种方法。

+0

我已经浏览了维基百科..实际上困扰我的东西是Object Graph,它是如何被GC程序维护和遍历的。 – 2009-04-21 20:19:24

0

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

就像我说的这是我知道的一种方法,并且在这方面有很多研究正在完成。

0

Garbage collection是一个很大的话题,并且有很多方法来实现它。

但简而言之最常见的,垃圾收集器保持到通过new运营商创造任何东西的所有引用的记录,即使操作者的使用是从你隐藏(例如,在一个Type.Create()方法)。每次向对象添加新引用时,如果需要,则确定该引用的并将其添加到列表中。只要它超出范围,就会删除引用。

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