垃圾收集器压缩堆中的对象时,是否会更改堆栈上的引用?


18

这似乎是一个简单的问题,但是在对该主题进行了大量阅读之后,我仍然没有找到明确的答案(也许是因为它是如此简单)。

我的问题是:当垃圾收集器压缩堆中的对象时,如何更新对堆栈中那些对象的引用?我可以想到两种可能的解决方案:

  1. 遍历堆栈(和堆中的引用)并更新引用以指向对象的新位置。类似于搬家,这就像给有您地址的任何人发送一封信,并要求他们用您的新地址更新他们的地址簿。
  2. 提供某种查找表。这就像在本地邮局留下转发地址。

垃圾收集器是否主要使用这两种方法之一?还有其他方法吗?都?



如果我错了,@ StevenBurnap会纠正我,但我认为您链接到的线程没有任何明确的答案。他们似乎也在猜测这个确切的问题。我可能读错了。如果他们确实提供了问题的答案,如果您不介意的话,我认为在这里为将来的SE用户(和我自己)总结答案会有所帮助
todorojo 2013年

您所谈论的事物的术语是“移动的垃圾收集器”。坦白地说,我不知道它们的使用频率。

Answers:


9

我对此没有专门知识,但是我的理解是通常使用第一种方法。

垃圾收集器必须无论如何都要分析堆栈,以查找从堆栈中引用堆中的什么东西。一旦决定移动某些东西,就必须无论如何都要纠正对它的引用,并且此时没有理由在堆和堆栈之间进行区分。

查找表方法原则上可以工作。但是,这将使所有指针访问都需要采取2个步骤。这将对正常运行时间产生巨大的性能影响。特别是对于许多小物体的使用情况。(在这种情况下,最先进的GC程序通常会超过引用计数。)


3
我要补充一点,我认为GC 除非可能必须尽量不要在堆上移动它们。在当今的多处理器世界中,当使用这些引用的程序正在运行时,它们需要将所有引用更新到堆上的某些内容时,这肯定是一场同步的噩梦。查找表可以简化此操作,但是我认为这是例外而不是常规,因此大多数GC可能必须锁定一些引用,移动内存,然后更新引用。+1有趣的问题,+ 1好的答案。
GlenPeterson

3
@GlenPeterson许多GC确实不会在堆上移动内容,也不会遇到此问题。但是根据定义,压缩的GC会将活动对象移动到碎片整理内存中。
btilly

@GlenPeterson很好地观察到,在堆上移动内容是一个巨大的同步难题,尽管如此,尽管GC压缩对正在运行的进程产生了巨大的连锁反应,但它常常被忽略。这是人们被告知要尽一切可能使对象保持最短生命期的唯一最大原因,以避免大堆更新导致压缩以保存长互斥量。忽略这些东西的行为方式可能会导致被人称为GC Freakout Mode的现象。
吉米·霍法

2
原始的Macintosh和Palm OS都使用查找表方法进行内存管理。指向表的指针称为句柄。重定位的GC必须绝对肯定地知道每一个对其移动的对象的引用的下落。为此目的使用单个表可以大大简化事情。
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.