垃圾回收器 (GC) 根是如何存储的?



我知道根是如何找到的,但问题是,(AFAIK(它们必须在运行时找到。为此,您需要一个可能会溢出的固定大小的容器或可调整大小的容器。我不想使用固定大小的容器,因为要确定要保留多少空间并不容易(而且可能会浪费(。可调整大小的容器似乎是最好的,但问题是,GC 在没有足够的空间时运行,因此可调整大小的容器将无法存储它需要的内容。那么在这些条件下,GC根是如何存储的呢?

GC 根是堆外部可以包含引用的位置 到堆内的对象。位置可以是任何可以 存储引用。通常是四到八个字节的内存存储 32 或 64 位地址,但也可以是机器寄存器或空间 在磁盘上。有时一个位置被称为"插槽",因为您可以"插槽" 在"正好是一个参考。经典的标记和扫荡收藏家作品 首先标记根引用的所有对象,然后继续 从那里进行追踪。

根的存储位置和方式取决于虚拟机,并且非常 当您考虑部分 GC、线程和 吉叮。但从概念上讲,这很简单。假设你有一个类似Python的 仅包含函数和全局变量以及以下代码的语言:

0: FOO = "hel"
1: BAR = "hi"
2: def foo(x):
3:    y = x + "there"
4:    <GC HERE>
5:    return
6: def bar(x):
7:    y = x + "lo"
8:    foo(y)
9:    return
10: bar(FOO)
11: ...

假设 GC 发生在指示的行上。调用堆栈看起来 像这样:

Return address to line 11
Reference to object "hello"
Return address to line 9
Reference to object "hellothere"

GC 将扫描此调用堆栈以区分返回 地址和引用,并标记它找到的对象。然后它 对于全局引用也会这样做。它们可以存储在 堆上的字典(哈希映射(并由单个根引用:

{name("FOO") : "hel", name("BAR") : "hi"}

请注意,存储所有根所需的空间很小。你只有 全局需要 8 个字节(一个引用(,全局需要 8 个字节 调用堆栈上的每个元素。您可能会用完堆栈空间并获得 堆栈溢出,但为堆栈预分配了 256kB,并且 适当的尾部调用优化 这不是问题。

最新更新