【JVM 学习】ParNew 为什么要STW

 

  • Serial 和 ParNew 在进行垃圾回收时,为什么需要stop the world?不stop thw world 可以吗?

在进行标记的时候,如果工作线程不停止的话,那么肯定会有新对象生成。这些对象是没有被标记的,里面可能有存活的对象,也可能有已经没有被引用的垃圾对象。那么在标记完后,进行回收时。要如何回收?

因为Serial 和 ParNew 是采用的复制算法。回收的时候,是需要把存活对象移到Survivor中的。而那些没有被标记的,有存活的,也有垃圾对象。显然不能全部移动到survivor 中的。

所以,在进行新生代回收的时候,是需要stop the world 的。

 

  • CMS 进行垃圾回收的时,为什么有些阶段,工作线程可以不停止?

在CMS 回收器中,回收是分为四个阶段的。初始标记、并发标记、重新标记、并发清理。其中,并发标记和并发清理是可以不停止工作线程的。

这里之可以不停止工作线程。也是和CMS 采用的回收算法有关的。

1、并发标记阶段

这个是比较耗时的,工作线程可以不停止。那么就有可能会有新对象进入老年代。这些新进入的对象。在重新标记阶段。是会被标记的。所以,这个阶段可以不停止工作线程。不过这个阶段对系统负载也是很高的(回收线程和工作线程同时存在)。

2、并发清理阶段

这个也是比较耗时的,工作线程也可以不停止。这里也有可能有新对象进入老年代的。这时候这些都是没有被标记的。其实,这里没有被标记的,就相当于不会被回收了。而CMS 采用的是标记-清理算法。这些没有被回收的是不影响的,大不了下一次在进行回收。不像ParNew 采用的是复制算法。需要把存活的移动到survivor 中(ParNew 其实也可以把没有标记的移动到survivor中,不过代价很大,因为大概率survivor 放不下会导致进入老年代)。所以,并发清理阶段,也是可以不停止工作线程的。

另外,在老年代回收时,有存活对象进入老年代的概率其实也是比较小的。大部分也会在新生代被回收掉。或者进入survivor区中。

 

这里回收垃圾时,是否stop the world。其实跟采用的回收算法是相关的。

 

  • CMS 不停止工作线程,会有哪些问题?

如果不停止工作线程,那么是有可能有存活对象进入老年代的。这时候就要有预留的空间给这些存活对象。所以,老年代回收时,不是等老年代满了才回收的。比如我们预留了10%空间,那么老年代使用率达到90%的时候,就会进行垃圾回收(老年代垃圾回收的情况不止这种,比如还有老年代空间担保机制,也可能会触发垃圾回收的)。

另外,如果在垃圾回收的时候,有新存活对象进入老年代,并且总大小超过了10%时,这时候放不下了!要怎么办?这个时候,是会触发 Concurrent Mode Failure 的。就是回收失败。之后,就会退化为 Serial old 垃圾回收器进行回收。会停止工作线程。重新标记,再回收。

 

所以,在CMS 中,为了不停止工作线程。是有可能引入其他问题。比如上面 Concurrent Mode Failure。这时候效率就很低了。需要花费很长时间进行old gc。

对于发生了 Concurrent Mode Failure 的时候,就要进行分析。是程序业务逻辑的问题,还是预留的空间大小太小等等。

  •  

 

 

你可能感兴趣的:(JVM,学习)