Hotspot 实现
大约 3 分钟JvmJavaJvm
Hotspot 实现
1 根节点枚举
所有收集器在根节点枚举过程中都要暂停用户线程, 执行过程中必须保障一致性, 不会出现分析过程中根节点还在变化。
在hotspot虚拟机中, 使用了一组OopMap的数据结构存放,记录下栈里和寄存器里哪些位置是引用(栈上也可能存放基本类型), 所以用空间换时间, 避免全栈扫描, 加快速度。
2 安全点
安全点:在特定的位置记录OopMap, 用户程序执行时只有到安全点才能停顿下来进行垃圾回收, 安全点既不能太少让收集器等待时间较长, 也不能过多导致垃圾收集频繁增大内存使用。
安全点特征:是否有让程序长时间执行的特征,即指令序列的复用, 如方法调用,循环跳转,异常跳转等。
2.1 安全点停顿方法
- 抢先式中断:在垃圾收集发生时, 中断全部用户线程, 如果用户线程不在安全点上恢复线程, 直到跑到安全点上.(几乎没有虚拟机使用)
- 主动式中断: 在安全点和创建对象的时候 设置标志位, 线程执行中主动轮询标志, 一旦发现标志为真,就在最近的安全点挂起
hotspot使用内存保护陷阱指令, 将页设置不可读, 执行时产生自陷异常信号, 通过异常处理器挂起线程实现等待。
3 安全区域
对于休眠、阻塞的线程无法执行到安全点, 定义了安全区域(被拉伸的安全点),确保在安全区域中不会发生引用关系的变化。
3.1 安全区域停顿方法
- 当线程执行到安全区域中时,会标识进入安全区域
- 当线程要离开安全区域时,首先检查虚拟机是否完成了垃圾回收中需要暂停用户线程的阶段,如果需要必须一直等待
4 记忆集和卡表
记忆集:记录从非收集区指向收集区域的指针集合的抽象数据结构,避免扫描完整的非收集区域。
4.1 实现方式
- 字长精度:精确到一个字长
- 对象精度:每个记录精确到一个对象,对象里包含跨代指针
- 卡精度:精确到一块内存区域,该区域内有对象含有跨代指针
Hotspot使用卡精度方式-卡表实现了记忆集,将非收集区化为相同大小的内存块(卡页),如果一个卡页包含跨代指针就将标识置为1,在垃圾收集时将该页的对象加入GC Root中扫描。
4.2 写屏障
通过写屏障维护卡表状态,是对引用类型赋值的一个aop切面,在赋值前后执行其他的动作。