Stop The World简称STW,指的是GC事件发生过程中,会产生引用程序的停顿。停顿产生时整个应用程序都会被暂停,没有任何响应,有点像卡死的感觉,这个停顿称为STW。
可达性分析算法中枚举根节点(GC Roots)会导致所有Java执行线程停顿。
被STW终端的应用程序线程会在完成GC之后恢复,频繁中断会让用户感觉像是网速不快造成电影卡带一样,所以我们需要减少STW 的发生。
并行(Parallel):指多条垃圾回收线程并行工作,但此时用户线程仍处于等待状态。如ParNew,Parallel Scavenge,Parallel Old.
串行(Serial): 相较于并行的概念,单线程执行。如果内存不够,则程序暂停,启动JVM垃圾回收器进行垃圾回收。回收万,在启动程序的线程。
并发(Concurrent):指用户线程与垃圾回收线程同时执行,但不一定是并行的,可能会交替执行。垃圾回收线程在执行时不会停顿用户程序的运行。
用户程序在继续运行,而垃圾收集程序线程运行于另一个CPU上,如CMS,G1.
程序执行时并非在所有地方都能停顿下来开始GC,只有在特定的位置才能停顿下来开始GC,这些位置称为安全点。
安全点的选择很重要,如果太少,用户线程长时间执行,可能导致GC 等待时间太长,如果太频繁,可能导致运行时的性能问题。大部分指令的知性时间都非常短暂,通常会根据是否具有让程序长时间执行的特征为标准。如选择一些执行时间较长的指令作为安全点,如方法调用,循环跳转和异常跳转等。
如何在GC发生时,检查所有线程都跑到最近的安全点停顿下来呢?
安全点机制保证了程序执行时,在不太长的时间内就会遇到可进入GC的安全点。但是程序不执行的时候呢?例如线程处于Sleep状态或Blocked状态,这时候线程无法相应JVM的中断请求,走到安全点去中断挂起,JVM也不太可能等待线程被唤醒。对于这种情况,就需要安全区域来解决。
**安全区域是指在一段代码片段中,对象的引用关系不会发生变化,在这个区域中的任何位置开始GC 都是安全的,**我们也可以将安全区域看做是被扩展了的安全点。
当线程运行到安全区域的代码时,首先标识已经进入了安全区域,如果这段时间发生GC,JVM会忽略标识为安全区域状态的线程。当线程即将离开安全区域时,会检查JVM是否已经完成GC,如果完成了,则继续运行,否则线程必须等待直到收到可以安全离开安全区域的信号为止。