![](https://img.haomeiwen.com/i29526965/ea8e8e05b063c0b4.png)
安全点
理解
用户线程在某一个指令位置停下来,紧接着垃圾收集线程开始工作,等当前用户线程再次接着执行时,后续的代码逻辑符合预期逻辑表现,没有受到垃圾收集处理的影响,那这个指令位置就是当前用户线程的安全点
实际上安全点选用标准
指令序列中的安全点不能太多,频繁的安全点检测是性能消耗,影响虚拟机处理用户线程的吞吐能力
指令序列中的安全点不能太少,用户线程长时间不到达安全点进行停顿操作,垃圾收集线程就不能开始执行垃圾收集过程,然而GC操作的触发,一般是某个用户线程触发空间分配需求时,堆区内存不足进而触发垃圾回收过程,只有垃圾回收过程执行完毕并能满足这个线程的内存空间申请需求后,这个用户线程才算被响应,GC过程长时间不能开始执行,就意味着某个用户线程长时间得不到响应,背离响应速度的核心需求
综合考虑,当下实际的安全点选择策略是一个标准:接下来要执行的指令是不是耗时比较长?实际上是使用耗时比较长的操作指令作为安全点,列如方法调用,循环跳转和异常跳转等指令
实现细节
抢先式中断(目前已经没有虚拟机采用这种方案)
中断所有用户线程,逐个检查这些线程是不是停顿在安全点,唤醒不在安全点的线程执行到安全点再停止执行,实现所有用户线程都停止在安全点
主动式中断
垃圾收集器设置一个中断标志,各个用户线程运行到安全点时判断中断标志决定是否停止执行,由此实现所有用户线程停止在其安全点,垃圾收集线程开始执行时,应该也有个用户线程是否在安全点的判断过程,要确保所有用户线程都暂停在安全点才可以开始垃圾回收过程
安全区域
理解
在一段连续的指令序列中,对象的引用关系不会发生变化,那这一段指令序列里的所有指令都是一个安全点,连起来的这个指令序列就是安全区域
安全区域要解决的实际问题
用户线程处于阻塞,睡眠等阶段,不会响应GC线程的中断请求,GC线程不能正常的开始执行,某一个用户线程的响应速度被拉长
等价理解:垃圾收集线程对安全区域的应用
垃圾收集线程工作前,要核对所有用户线程是不是进入了对应的安全点,如果被核对的用户线程没有响应垃圾收集线程的中断请求,一直被阻塞在某一个安全区域里的指令之前,那么垃圾收集线程可以认为这个用户线程也是处于安全点状态的
GC过程完成时垃圾收集线程会重置安全点中断标志,在并发垃圾回收过程中,原本没有响应垃圾收集线程中断请求的用户线程解除了阻塞状态,开始继续执行,到达指令序列安全区域边界点的时候同样会检测中断标志,进而停止执行,不影响垃圾收集过程的安全性
总结
实际上的安全点选用标准再加一个规则:涉及到对象引用关系变化的操作指令也视为一个安全点,两个这样的安全点之间连城一片的指令序列就是一个安全区域,同样的,这个安全区域里的所有指令都是安全点,只是这里面的安全点不会触发也不需要触发垃圾收集器的中断请求检测
网友评论