首先内存模型不一样:

  1. CMS还是采用传统的年轻代(包括一个伊甸区,两个幸存区)、老年代。
  2. G1是把内存切分成大小相等的区域(region),逻辑上把他们划分为伊甸区、幸存区、老年区。

CMS(cocurrent mark and sweep)major gc步骤:

  1. init mark:从roots出发(线程、静态引用、新生代)遍历存活对象;这个阶段应用线程暂停。
  2. cocurrent mark:多个垃圾回收线程同时遍历JVM内存的存活对象;这个阶段应用线程是运行状态。
  3. remark:上个阶段中,可能产生新的存活对象或者垃圾对象,暂停应用,把上述对象遍历处理;这个阶段应用程序暂定。
  4. courrent sweep:多个线程同步的清理垃圾对象;这个阶段应用城市是运行状态。
  5. reset:复位,准备下一次垃圾回收过程。

G1 major gc步骤:

  1. init mark:跟CMS一样,从roots出发(主要是survivor regions出发)遍历regions中的存活对象;这个阶段应用线程暂停。
  2. courrent mark:多线程同步遍历所有(包括年轻代)regions中的对象,如果发现某个region里的对象全是垃圾对象,则直接将regions进行释放,这也是为啥叫garbage first的原因;这个阶段应用线程是运行状态。
  3. remark:上个阶段中,可能产生新的存活对象或者垃圾对象,暂停应用,把上述对象遍历处理;这个阶段应用程序暂定。
  4. copy/clean:回收都是垃圾的region,拣出垃圾对象最多的regions,将其中的存活对象分散(evacuate)到其他region是中或者拷贝到空region当中,然后进行回收释放。
  5. reset:复位,准备下一次垃圾回收过程。

G1的优势:

  1. G1采用region的方式,实际上是清理压缩的过程,不会产生内存碎片;而CMS只清除,不会移动存活对象,可能会产生很多的内存碎片,除非full GC的情况。
  2. G1在垃圾回收的时候,可以根据预定的时间进行垃圾回收:根据时间限制,挑选垃圾最多的regions进行回收;CMS是一个全量过程,垃圾回收时间不能把控;这样G1就能灵活响应程序需求。

 

https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html

https://docs.oracle.com/javase/9/gctuning/concurrent-mark-sweep-cms-collector.htm#JSGCT-GUID-FF8150AC-73D9-4780-91DD-148E63FA1BFF