乔微博 发表于 2022-3-26 10:36:40

JVM-GC时的安全点Safe Point与安全区域Safe Region


[*]问题的提出:JVM的GC实在任何时刻都会发生吗?
[*]先给出答案:不是的,只有stw(stop the world)即用户线程停下来后才会执行,那么用户线程千千万,如何治理呢?有办法,就是此处的安全点和安全区域。
1.什么是安全点Safe Point

程序执行时并非在所有地方都能停顿下来开始GC , 只有在特定的位置才能停顿下来开始GC , 这些位置称为“ 安全点(Safepoint)。
2.安全点的选择

安全点的选择很重要, 如果太少可能导致GC 等待的时间太长, 如果太频繁可能导致运行时的性能问题。大部分指令的执行时间都非常短暂,通常会根据“ 是否具有让程序长时间执行的特征” 为标准。比如: 选择一些执行时间较长的指令作为safe Point ,如:


[*]循环的末尾
[*]方法临返回前
[*]调用方法之后
[*]抛异常的位置
3. GC时线程的中断策略

如何在GC生时, 检查所有线程都跑到最近的安全点停顿下来呢?


[*]抢先式中断: ( 目前没有虚拟机采用了)
首先中断所有线程。如果还有线程不在安全点, 就恢复线程, 让线程跑到安全点。
[*]主动式中断:
设置一个中断标志, 各个线程运行到Safe Point的时候主动轮询这个标志,如果中断标志为真, 则将自己进行中断挂起。(客栈门上安装了一个显示器,上面会显示ture,或者false。如果系统需要垃圾回收,就会更新这个状态为true,线程到了客栈后看到为true,就进店别别出来了。)
4.安全区域Safe Region


[*] SafePoint 机制保证了程序执行时, 在不太长的时间内就会遇到可进入GC的safepoint 。但是, 程序“ 不执行” 的时候呢? 例如线程处于Sleep 状态或Blocked 状态, 这时候线程无法响应JVM的中断请求, “ 走” 到安全点去中断挂起,JVM也不太可能等待线程被唤醒。对于这种情况, 就需要安全区域(Safe Region) 来解决。
[*] 安全区域是指在一段代码片段中, 对象的引用关系不会发生变化, 在这个区域中的任何位置开始GC 都是安全的。我们也可以把Safe Region 看做是被扩展了的Safepoint
5.安全区域Safe Region-执行流程

实际执行时:
1 、当线程运行到 Safe Region 的代码时, 首先标识己经进入了safe Region ,如果这段时间内发生GC ,JVM会忽略标识为 Safe Region 状态的线程(认为它是安全的):
2 、当线程即将离开时, 会检查JVM是否己经完成GC , 如果完成 , 则继续运行, 否则线程必须等待直到收到可以安全离开Safe Region 的信号为止。


[*]一句话,睡觉可以,请先进入酒店再睡觉,并且进去是在屏幕上说一声我进入安全区域了,在睡觉。这样做的目的就是当要GC的时候不至于找不到你,如果看到屏幕上有你这个线程的名字,就知道你是安全的,就会忽略你;
[*]你(线程)睡醒了要出门了。抬头看看大屏幕是不是安全在出去(true),如果不安全(false)就在酒店待着,别出门,等到gc完成后,状态变为false在出门。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: JVM-GC时的安全点Safe Point与安全区域Safe Region