1.安全点
因为在JVM进行垃圾回收的时候,需要进行stw。但是呢,程序已经跑起来了,不能说停就停,因此需要找到一个合适的位置才能停止。这个合适的位置就叫做安全点,也就是说,当代码执行到安全点的时候,才会停止下来进行GC操作。因此就会有两个问题产生,安全点过多会导致GC过于频繁,安全点过少,就会导致GC等待的时间长,可能在等待的过程中产生OOM。
接下来问题出现了,在多线程时,如果一个线程到达了安全点,开启了GC,那么其他的线程如何让他们到安全点停下来。
- 抢占式中断,先把所有线程都强制停止,检查一下到没到安全点,没有的话,重启,直到他们到达安全点再停止。
- 主动式中断,设置一个全局的中断标志,当GC发生的时候将这个标志设置为true。当线程经过安全点的时候就去主动轮询这个中断标志。如果为true,则主动中断,否则继续执行。
2.安全区域
这个安全区域是安全点的扩展,在安全区域中对象的引用关系不能改变(回想一下在进行垃圾回收的时候,JVM需要进行可达性分析,这个可达性分析主要也是和对象的引用关系相关联)。当GC出现的时候如果这个线程在安全区域中,继续执行就可以,因为引用关系不变,不会导致垃圾对象的产生。但是如果即将离开安全区域,GC还没执行完,那只能阻塞等待了。
最后一点
无论是安全点还是安全区域,JVM在进行垃圾回收的时候,必须等待所有线程都进入“安全”位置的时候才能进行GC。