我最近阅读了关于垃圾回收的一些文章(主要是针对Java),但仍有一个问题未解答:JVM(或运行时系统)如何跟踪当前活动对象?
我理解这些对象是当前在堆栈上的对象,即所有局部变量或函数参数,这些都是对象。但这种方法的问题在于,每当运行时系统检查堆栈上的当前内容时,它如何区分引用变量和简单的整型变量?它不能,对吧?
因此,必须有一种机制允许运行时系统构建初始的活动对象列表,以便传递给标记-清除阶段。
我最近阅读了关于垃圾回收的一些文章(主要是针对Java),但仍有一个问题未解答:JVM(或运行时系统)如何跟踪当前活动对象?
我理解这些对象是当前在堆栈上的对象,即所有局部变量或函数参数,这些都是对象。但这种方法的问题在于,每当运行时系统检查堆栈上的当前内容时,它如何区分引用变量和简单的整型变量?它不能,对吧?
因此,必须有一种机制允许运行时系统构建初始的活动对象列表,以便传递给标记-清除阶段。
a. 它在4字节边界上对齐。
b. 插槽中的值指向堆区域(在下限和上限之间)。
c. 分配位设置。分配位是一个标志,指示与其相应的内存位置是否已分配。
这是我的参考资料:http://www.ibm.com/developerworks/ibm/library/i-garbage2/。
还有一些其他技术可以找到根集(不是在Java中)。例如,因为指针通常在4/8字节边界上对齐,所以第一位可以用于指示插槽是原始值还是指针:对于原始值,第一位设置为1。这样做的缺点是您只有31位(32位架构)来表示整数,并且对原始值的每个操作都涉及移位,这显然是一个开销。
此外,您可以使所有类型(包括int)都在堆上分配。也就是说,所有东西都是对象。然后,堆栈帧中的所有插槽都是引用。
0 : [RAX, RBX]
4 : [RAX, [RSP+0]]
10 : [RBX, RSI, [RSP+0]]
...
120 : [[RSP+0],[RSP+8]]
[RSP+x]
表示堆栈位置,R??
表示寄存器。因此,如果线程在偏移量为10的汇编指令处停止,并且运行了 gc 循环,则 HotSpot 知道三个根位于 RBX
、RSI
和 [RSP+0]
中。它跟踪这些根并更新指针,如果必须移动对象的话。