目录
SafePoint安全点与Stop The World
在介绍各个垃圾回收器之前,先了解SafePoint的概念。
- 在进行对象可达性分析过程中,工作必须在一个能确保一致性的快照中进行——这里一致性的意思是指整个分析期间整个执行系列看起来就像被冻结在某个时间点上,不可以出现分析过程中对象引用关系还在不断变化的情况。
- 这就导致了GC进行时必须停顿所有的java执行线程(Stop The World)
- 当系统停顿下来之后,并不需要一个不漏地检查完所有的执行上下文和全局引用位置,虚拟机通过一组成为OopMap的数据结构,直接得知哪些地方存放着对象引用。
- 在类加载完成的时候,Hotspot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中也会在特定的位置记录下栈和寄存器中哪些位置是引用。
- 但是如果为每一条指令都生成对应的OopMap,那么将需要大量的额外空间。前面也提到了,是在“特定位置”上记录了这些信息,这些位置就叫做SafePoint安全点。程序执行时并非在所有的位置都可以停顿下来开始GC,只有在到达安全点时才能暂停。
-
如何在GC发生时让所有的线程都跑到最近的安全点上再停顿下来?
有两种方式:- 抢先式中断:在GC发生时,先把所有的线程中断,如果发现有线程中断的地方不在安全点上,就恢复线程让它跑到安全点再停下。
- 主动式中断:当GC需要中断线程时,不直接对线程进行操作,而是设置一个标志,各个线程在执行到安全点时,去主动轮询这个标志,如果发现需要暂停,就自己中断挂起。大部分虚拟机都是使用的这种方式。
-
什么地方可以放SafePoint?
理论上来讲,每一条指令都要一个SafePoint,但是为了减少性能消耗,要尽可能的减少SafePoint的数量。
通过JIT编译的代码里,在所有的方法返回之前,或者所有的无界循环回跳之前,放一个SafePoint,以防止发生stw时该线程不能暂停。
比如for(int 1=0;i<100;i++)这种有界循环是没有SafePoint的。 -
SafePoint的作用?
SafePoint机制可以Stop The World,保证一致性的工作环境,不仅仅是在GC的时候用,有很多其他地方也会用它来Stop The World,阻塞所有Java线程,从而可以安全地进行一些操作。 -
安全域是什么?
SafePoint保障了程序执行时,在不太长时间内就会遇到可进入GC的安全点,但是程序不执行的时候呢?典型的例子就是线程处于Sleep或者Blocked状态,无法响应JVM的中断请求。