Closed. This question needs to be more focused。它当前不接受答案。












想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。

3年前关闭。



Improve this question




用外行术语来说,垃圾收集机制是如何工作的?

如何确定对象可用于垃圾收集?

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

最佳答案

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

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

最简单的方法是正确进行引用计数。每当您创建对对象的引用时,该对象上的内部计数器都会增加,当您偶然引用该引用或该引用不再在作用域内时,(以前)目标对象上的计数器也会减少。当此计数器达到零时,将不再引用该对象,并且可以将其释放。

引用计数垃圾收集器的问题在于它们无法处理循环数据。如果对象A引用了对象B,而对象B又引用了(直接或间接)对象A,则即使链中没有任何对象在链外被引用(因此不是'根本无法访问该程序)。

另一方面,标记和扫描算法可以处理此问题。标记和清除算法的工作方式是定期停止程序的执行,将程序分配的每个项目标记为不可访问。然后,程序将遍历程序具有的所有变量并将其指向的变量标记为可访问。如果这些分配中的任何一个包含对程序中其他数据的引用,则该数据也将被标记为可访问等。

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

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

为了对此进行改进,可以使用所谓的“世代垃圾收集”扩展标记和清除算法。在这种模式下,系统中已存在一定数量垃圾回收的对象将被提升到较旧的一代,而该对象不会经常检查。

这会提高效率,因为对象趋于年轻化(例如,在循环内更改字符串,可能导致数百个生命周期)或寿命很长(用于表示应用程序主窗口的对象,或者Servlet的数据库连接)。

可以在Wikipedia上找到更多详细信息。

根据评论添加:

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

关于memory-management - 垃圾收集机制如何工作? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/774357/

10-12 03:46