垃圾回收时的安全点与安全区

      垃圾回收时,首先要枚举所有GC Roots节点。然而枚举GC Roots节点是需要停顿执行系统的。执行系统的停顿不可以过久,否则会影响整个系统的执行。为了能快速计算出对象内什么偏移量上是什么类型的数据,从而迅速完成枚举,HotSpot使用OopMap。OopMap是个Map,记录了所有必要信息的具体地址。

      然而,OopMap是需要空间的。若每一条指令都创建一个对应的OopMap,需要大量的额外空间。于是HotSpot并没有为每条指令都生成OopMap,而是只在某些特定位置上生成。这些位置称之为“安全点”(Safepoint)。

      程序执行时,只有当运行到安全点时,GC才会被执行。安全点通常具有让程序长时间运行这个特征。

      当GC发生时,需要让所有线程都运行到最近的安全点上再停顿下来。有两种方案可选:

①   抢先式中断:不需要线程的执行代码配合,GC发生时让所有线程全部强制中断。若有线程中断的位置不在安全点上,就令其恢复,执行到安全点再中断。

②   主动式中断: 当GC发生时,设置一个公共的标志。各个线程执行时,会主动去轮询这个标志。当发现中断标志为真时,就把自己中断,并挂起。轮询标志和安全点一定是重合的。  

目前几乎所有的虚拟机都不会采用主动式中断。

 

      对于那些Sleep或者Blocked的线程,不会去轮询公共标志,所以也就不会响应JVM的中断请求。对于这种情况,需要安全区域来解决。

      所谓安全区域(Safe Region),可以看做是一个范围扩展了的安全点。在安全区域中,任意地方开始GC都是安全的。

      当线程执行到安全区域中的代码时,就会标识自己进入了安全区域。当JVM发起GC时,就不再管具有Safe Region状态的线程了。当线程要离开安全区域时,会检查系统是否已经完成了GC过程。若完成了,就继续执行;否则会等到可以离开安全区域的信号为止。

你可能感兴趣的:(Java,深入理解Java虚拟机,JVM)