一、STW (Stop The World)
STW的概念
JVM在执行GC垃圾收集或者其他特殊任务(比如分派GC、thread dump、死锁检查等)时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外),表现为全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互。
起因
在JVM系列之如何判断对象已死中可达性分析需要从GC Roots节点寻找引用链,可作为GC Roots的节点主要为全局引用(常量或静态变量)和执行上下文(本地变量表),如果要追个检查其中的引用必然要花费很多时间,而且为了保证检查结果的准确性,就得要求在检查期间整个系统被终结在某个时间点上,否则在检查前后对象的引用关系没办法保证一致。
造成的后果
系统出现卡顿,用户体验差
解决方案
为了在停顿过程中更快速精准的检查完所有GC Roots的引用位置,在HotSpot的实现中使用OopMap的数据结构来存放对象的引用,但依然没办法从根本上完全解决停顿问题。
二、安全点(SafePoint)
安全点的概念
前面在引入OopMap之后,又有一个问题就是导致引用关系变化的指令非常多,如果为每条指令都生成OopMap数据显然需要大量内存开销,所以实际上只在特定位置记录,这个特定位置就是安全点(SafePoint)。
也就是说程序执行过程中并非所有地方都能停下来GC,只有在所有线程都到达最近的安全点时才能暂停进行GC。
安全点的选定
方法调用、循环跳转、异常跳转等。
实现过程
采用主动式中断,各个线程每当执行到安全点时都会主动轮询某个标志看是否触发线程中断。当GC需要中断线程时就将该标志置为真,各线程就会陆续主动触发暂停实现等待。
三、安全区域(SafeRegion)
安全区域的引入
SafePoint机制保证了在运行较短的时间内就会遇到可执行GC的SafePoint,那么当程序不执行时(Sleep或者Blocked状态)就没办法到达SafePoint,然后引入了SafeRegion。
安全区域的概念
在一段代码片段中,引用关系不会发生变化,也就是说在这个区域中任意地方开始GC都是安全的。
实现过程
当线程执行到SafeRegion时会标识自己进入SafeRegion,JVM在此期间发起GC就不用管该线程。当线程离开SafeRegion时就得检查GC是否完成,如果完成则继续执行,否则等待。