Loading

JVM SafePoint

date: 2020-11-12 17:58:00
updated: 2020-11-16 10:03:00

JVM SafePoint

在多线程环境下,为了能正确回收不再使用的内存,安全回收需要满足以下两个条件

  1. 堆内存的变化是受控制的,最好所有的线程都停止
  2. 堆中的对象是已知的,不再使用的对象都可以找到

∴ JVM 是在 SafePoint 点时才进行回收,所谓 SafePoint 即Java线程执行到某个位置时,JVM能够安全可控地回收对象

如何到达 SafePoint

说到这里就要提到如何使线程中断,一般有两种方式:主动式和被动式。主动式JVM设置一个全局变量,线程去按照某种策略检查这个变量一旦发现是Safe Point就主动挂起,被动式就是发个信号,例如关机、Control+C,带来的问题就是不可控,发信号的时候不知道线程处于什么状态。这里HostSop虚拟机采用的是主动式使线程中断。

既然JVM使用的是主动性主动到达安全点,那么应该在什么地方设置全局变量呢?显然不能随意设置全局变量,进入安全点有个默认策略那就是:“避免程序长时间运行而不进入Safe Point”,程序要GC了必须要等线程进入安全点,如果线程长时间不进入安全点这样就比较糟糕了,因此安全点主要咋以下位置设置:

  1. 循环的末尾

  2. 方法返回前

  3. 调用方法的call之后

  4. 抛出异常的位置

安全区域

安全点完美的解决了如何进入GC问题,实际情况可能比这个更复杂,但是如果程序长时间不执行,比如线程调用的sleep方法,这时候程序无法响应JVM中断请求这时候线程无法到达安全点,显然JVM也不可能等待程序唤醒,这时候就需要安全区域了。

安全区域是指一段代码片中,引用关系不会发生变化,在这个区域任何地方GC都是安全的,安全区域可以看做是安全点的一个扩展。线程执行到安全区域的代码时,首先标识自己进入了安全区域,这样GC时就不用管进入安全区域的线层了,线层要离开安全区域时就检查JVM是否完成了GC Roots枚举,如果完成就继续执行,如果没有完成就等待直到收到可以安全离开的信号。

posted @ 2020-11-25 16:01  猫熊小才天  阅读(150)  评论(0编辑  收藏  举报