📖 JVM 之 OopMap 和 RememberSet
🔖 OopMap
OopMap 有什么用?
OopMap 用于枚举GCRoots
- 当垃圾回收发生时,收集线程 会 对栈上的内存进行扫描,看看哪些位置上存储了 Reference 类型,就
意味着这个引用
所指向的对象
在这一次垃圾回收过程中不能进行回收。
当然问题就出现了~
-
栈上的本地变量表里面只有一部分数据是 Reference 类型的 ,为了
避免每次垃圾回收时都要扫描整个栈
,所以采用了 空间换时间 的策略。在某个(安全点)把栈上代表引用的位置记录下来,GC时直接读取,以防全部扫描。 -
HotSpot 虚拟机采用了一种叫做
OopMap
的数据结构用于记录上述引用(OopMap也帮助了HotSpot实现了准确GC),OopMap记录了栈上本地变量到堆上对象的引用关系
,这些引用关系对象不能够回收,并且可以作为根节点来进行可达性分析,查找出不能够回收的对象。 -
一个线程意味着一个栈,一个栈由多个栈帧组成,一个栈帧对应着一个方法,一个方法中可能有多个安全点,GC 发生时,程序首先运行到最近的一个安全点停下来,STW 并且
更新自己的 OopMap
, 记录栈上哪些位置代表引用,枚举根节点时,递归遍历每个栈帧的OopMap,通过栈中记录的被引用的对象内存地址,即可找到这些对象(GC Roots),所以说一个方法可能有多个OopMap,每一个记录的也只仅限于自己的那一段代码。
🔖 RememberSet
RememberSet 是什么?
-
每个
region
都有一个记忆集(Rset),记忆集会记录下当前这个region中的对象被哪些对象所引用
。例如,region2 中的两个对象分别被region1中的对象和region3中的对象所引用,那么,region2的记忆集记录的就是region1和region3中的引用region2的对象的引用。 -
这样一来在回收region2的时候,就不用扫描全部的region了,只需要访问记忆集,就知道当前region2里面的对象被哪些对象所引用,判断其是不是存活对象。