JVM 安全区域的理解

347 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

上文提到了安全点的概念,为的是减少生成OOPMap的内存开销,以及为中断线程为GC提供一个一致性快照提供合理的中断点

那么遗留下来的问题,当GC开始前,线程已经进入Sleep或Blocked状态呢?

在挂起状态的线程是无法轮询标志的,也就无法自动前往最近的安全点,如若是长时间的挂起状态直到GC结束后才开始执行还好,若GC中途线程结束挂起开始运行,这可如何是好?这种风险虚拟机可以但没必要承担的

所以就引入安全区域的概念

安全区域(Safe Region)

安全区域是指能够确保在某一段代码片段之中,引用关系不会发生变化,因此,在这个区域中任 意地方开始垃圾收集都是安全的。我们也可以把安全区域看作被扩展拉伸了的安全点。 --摘自《深入理解Java虚拟机》

当线程进入Sleep或Blocked状态时,它只是在等待,等待拿到锁或者结束睡眠,本身的状态不会再发生改变所以就类似于到达了一个安全点,在这个区域内任意一行代码,全都是安全点,这就是安全区域

代码示例:

public void test() {
    Object o1 = new Object();
    o1.setObj(new Object());
    
    // Safe Region 的开始
    System.out.println(123);
    System.out.println(o1.getClass());
    // Safe Region 的结束
    // 在此之间对象引用关系并没有发生改变
}

在虚拟机执行线程的过程中,如果线程进入了安全区域,则会标识自身已进入,当GC发起时,收集器就不回去处理这些线程,当线程离开安全区域时,会检查jvm是否已经完成了根节点枚举或者已经过了需要暂停用户线程的阶段,如果是则继续执行,否就持续等待直到获得可以离开的信号

image.png

GC Roots枚举执行流程浅分析

(流程图绘画可能有点杂乱)

image.png