g1和cms介绍(适合面试)

CMS垃圾回收器:

CMS是作用于老年代的并发垃圾回收器,使用标记清除算法,工作流程是:初始标记,并发标记,再次标记,并发清除

优点

  • 耗时最长的并发标记和并发清除阶段gc线程和用户线程是并发执行的,因此其STW时间短,适合对延迟有要求的任务

缺点:

  • CMS在老年代使用的是标记清除算法,会产生大量内存碎片
  • GC线程与用户线程并发执行,二者会抢占cpu,并且会产生浮动垃圾

初始标记阶段会发生短暂的stw,用于标记GCRoot对象能够直接到达的对象

并发标记阶段gc线程根据GCRoot对象标记可到到的存活对象,应用程序可以和gc线程并行进行,不需要stw

再次标记阶段会进行stw,目的是为了修正因为并发标记阶段应用程序和gc线程并发执行产生的浮动垃圾

并发清除阶段gc线程清除垃圾对象,gc线程和应用线程并发执行因此会产生浮动垃圾,在下一次gc清理该浮动垃圾

G1垃圾回收器:

G1垃圾回收器是一款可以同时管理新生代和老年代,在老年代使用标记整理算法,其最大的特点是将内存划分为多个大小相等region,每个region都可以作为伊甸区,survivor区,老年代

优点:

  • 老年代使用标记整理算法,不会产生内存碎片
  • 使用region,不会出现新生代或者老年代分配空间过大而造成浪费
  • 每次只选择垃圾对象多的region,而不是整个堆,大幅减少了STW时间(但region与region之间是有依赖关系的,g1维护了一个Remembered Set记忆集记录了region的依赖关系,只需要扫描关联的region,而不是整个堆)
  • 用于可预测停顿的模型,可以指定STW时间(也就是可预测停顿),比如在一小时内垃圾回收导致的"stop the world"时间不超过一分钟。

G1垃圾回收过程主要包含三个阶段,

  1. 当伊甸区慢时,年轻代使用标记复制算法进行回收
  2. 当堆空间的内存占用达到阈值时,老年代使用标记整理算法进行回收,前三个过程和cms类似,都为初始标记,并发标记,并发清除,区别在于最终清除阶段,CMS是并发的,而G1会进行STW,不是并发的
  3. 当老年代占比达到阈值,触发混合回收,为了防止堆内存耗尽,会回收所有年轻代和部分老年代

CMS和G1比较:

  1. G1和CMS都分为4个阶段,前三个阶段基本相同都为初始标记,并发标记,再次标记,区别在于最后清除阶段CMS是并发的,G1不是并发的,因此CMS最终会产生浮动垃圾,只能等待下次gc才能清除
  2. G1可以管理整个堆,而CMS只能作用于老年代,并且CMS在老年代使用的是标记清除算法,会产生内存碎片,而G1使用标记整理算法,不会产生内存碎片
  3. G1相比于CMS最大的区别是G1将内存划分为大小相等的Region,可以选择垃圾对象多的Region而不是整个堆从而减少STW,同时使用Region可以更精确控制收集,我们可以手动明确一个垃圾回收的最大时间

补充:

因为耗时最长的并发标记和并发清除gc线程和应用线程都是并发执行的,所以总体来看cms收集器的gc线程和应用线程是并发执行的

G1之所以能做到回收时间可控,主要是得益于Region这个结构。G1会记录每个Region里的对象有多少是垃圾对象,如果要对某个Region进行垃圾回收,他会计算出对该Region回收的时间,可以回收多少垃圾。

实际上除了CMS收集器,其他都不存在只针对老年代的收集。

但是每个region之间是有互相引用的依赖关系的!这导致在MinorGC的时候会同时对老年代进行扫描(甚至是整个堆扫描),那就会导致MinorGC的效率低下,时间变长!
解决方法是:维护一个Remebered Set集合来存放各个Region之间的引用关系!当进行GC Roots Tracing 的时候就可以只扫描set里的关联region!而不用全堆扫描啦!!! 在GC根节点的枚举范围中加入Remembered Set即可保证不对全堆扫描也不会有遗漏了。