Memory 垃圾收集器(GC)根如何存储?

Memory 垃圾收集器(GC)根如何存储?,memory,compiler-construction,garbage-collection,containers,gc-roots,Memory,Compiler Construction,Garbage Collection,Containers,Gc Roots,我知道如何找到根,但问题是,它们必须在运行时找到。为此,您需要一个可能溢出的固定大小容器或一个可调整大小的容器。我不想使用固定大小的容器,因为要知道要保留多少空间并不容易(这可能是浪费)。可调整大小的容器似乎是最好的,但问题是,GC在没有足够空间时运行,因此可调整大小的容器将无法存储它需要的内容。那么,在这些条件下,GC根是如何存储的呢?GC根是堆外可以包含引用的位置 到堆内的对象。一个位置可以是任何可以 存储一个引用。通常是4或8字节的内存存储 32或64位地址,但也可以是机器寄存器或空间 在

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

GC根是堆外可以包含引用的位置 到堆内的对象。一个位置可以是任何可以 存储一个引用。通常是4或8字节的内存存储 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将扫描这个调用堆栈,区分返回 地址和引用,并标记找到的对象。然后它 将对全局引用执行相同的操作。它们可以储存在一个容器中 堆上由单个根引用的字典(hashmap):

{name("FOO") : "hel", name("BAR") : "hi"}
请注意,存储所有根所需的空间很小。只有你 全局值需要八个字节(一个引用),全局值需要八个字节 调用堆栈上的每个元素。您可能会耗尽堆栈空间并获取 堆栈溢出,但为堆栈预分配了256kb,并且
正确的尾部调用优化这不是问题。

为什么要存储它们?这不是一个开玩笑的问题。例如,堆栈上的每个引用都是根引用,但它们都位于堆栈上,并且它们不会去任何地方(只要您正在执行stop the world集合)。@rici--您指的是什么堆栈?堆栈&堆堆栈?您知道每次GC调用都会找到GC根,对吗?GC结构也在堆外,而GC在堆上运行。@Eugene——请原谅我的无知,但是每次GC调用都会发现GC根是什么意思?你是说每个分配吗?最明显的是:堆栈引用。如果某个东西在堆栈上,那么它显然正在使用中。因此,这是根的完美候选。要找到这些,当然需要扫描线程堆栈。为了准确起见,您的应用程序被冻结时,这些文件将被扫描。
{name("FOO") : "hel", name("BAR") : "hi"}