跳至主要內容

Hotspot 实现

blacklad大约 3 分钟JvmJavaJvm

Hotspot 实现

1 根节点枚举

所有收集器在根节点枚举过程中都要暂停用户线程, 执行过程中必须保障一致性, 不会出现分析过程中根节点还在变化。

在hotspot虚拟机中, 使用了一组OopMap的数据结构存放,记录下栈里和寄存器里哪些位置是引用(栈上也可能存放基本类型), 所以用空间换时间, 避免全栈扫描, 加快速度。

2 安全点

安全点:在特定的位置记录OopMap, 用户程序执行时只有到安全点才能停顿下来进行垃圾回收, 安全点既不能太少让收集器等待时间较长, 也不能过多导致垃圾收集频繁增大内存使用。

安全点特征:是否有让程序长时间执行的特征,即指令序列的复用, 如方法调用,循环跳转,异常跳转等。

2.1 安全点停顿方法

  1. 抢先式中断:在垃圾收集发生时, 中断全部用户线程, 如果用户线程不在安全点上恢复线程, 直到跑到安全点上.(几乎没有虚拟机使用)
  2. 主动式中断: 在安全点和创建对象的时候 设置标志位, 线程执行中主动轮询标志, 一旦发现标志为真,就在最近的安全点挂起

hotspot使用内存保护陷阱指令, 将页设置不可读, 执行时产生自陷异常信号, 通过异常处理器挂起线程实现等待。

3 安全区域

对于休眠、阻塞的线程无法执行到安全点, 定义了安全区域(被拉伸的安全点),确保在安全区域中不会发生引用关系的变化。

3.1 安全区域停顿方法

  1. 当线程执行到安全区域中时,会标识进入安全区域
  2. 当线程要离开安全区域时,首先检查虚拟机是否完成了垃圾回收中需要暂停用户线程的阶段,如果需要必须一直等待

4 记忆集和卡表

记忆集:记录从非收集区指向收集区域的指针集合的抽象数据结构,避免扫描完整的非收集区域。

4.1 实现方式

  1. 字长精度:精确到一个字长
  2. 对象精度:每个记录精确到一个对象,对象里包含跨代指针
  3. 卡精度:精确到一块内存区域,该区域内有对象含有跨代指针

Hotspot使用卡精度方式-卡表实现了记忆集,将非收集区化为相同大小的内存块(卡页),如果一个卡页包含跨代指针就将标识置为1,在垃圾收集时将该页的对象加入GC Root中扫描。

4.2 写屏障

通过写屏障维护卡表状态,是对引用类型赋值的一个aop切面,在赋值前后执行其他的动作。

4.3 并发标记过程中的问题

三色标记法open in new window三色标记法open in new window

上次编辑于:
贡献者: blacklad