JVM虚拟机垃圾回收CMS和G1的区别

这是我开通博客园的第一篇文章,有错误的地方,请大家指正,之所以开通博客园,是受到以为学长的影响,看着他在博客园的博客,我知道写博客不仅是自我复习的一个过程,也是一个和别人沟通的窗口,所以我打算向学长学习,以后多记录博客,加深知识点的印象。

CMS和G1的区别是我最近在面试过程中经常被问到的一个问题,虽然能答出几点出来,但是自己并不太满意,网上关于两者的对比也没有特别完善的文章,于是打算记录下这边文章

首先我把答案给出来,然后再去分析为什么会这样

 

CMS

G1

JDK版本

1.6以上

1.7以上

回收算法

标记——清除

标记——整理

运行环境

针对70G以内的堆内存

可针好几百G的大内存

回收区域

老年代

新生代和老年代

内存布局

传统连续的新生代和老年代区域

Region(将新生代和老年代切分成Region,默认一个Region 1 M,默认2048块)

浮动垃圾

内存碎片

全堆扫描

回收时间可控

对象进入老年代的年龄

6

15

空间动态调整

是(新生代5%-60%动态调整,一般不需求指定)

调优参数

多(近百个)

少(十几个)

 

1、CMS

CMS(Concurrent Mark Sweep),我们可以轻易地从命名上看出,它是一个并发的,然后是基于标记——清理的垃圾回收器,它清理垃圾的步骤大致分为四步:

  1. 初始标记
  2. 并发标记
  3. 重新标记
  4. 并发清理

 

 

 (图片是出自网上,如有侵犯请联系我,谢谢)

初始标记只要是找到GC Roots,所以是一个很快的过程,并发标记和用户线程一起,通过GC Roots找到存活的对象,重新标记主要是修复在并发标记阶段的发生了改变的对象,这个阶段会Stop the World;

并发清理则是保留上一步骤标记出的存活对象,清理掉其他对象,正因为采用并发清理,所以在清理的过程中用户线程又会产生垃圾,而导致浮动垃圾,只能通过下次垃圾回收进行处理;

因为cms采用的是标记清理,所以会导致内存空间不连续,从而产生内存碎片

此处要清楚,CMS的垃圾回收的内存模型还是以我们常用的新生代,老年代的结构,如下图所示:

2.G1

G1(Garbage-First),以分而治之的思想将堆内存分为若干个等大的Region块,虽然还是保留了新生代,老年代的概念,但是G1主要是以Region为单位进行垃圾回收,G1的分块大体结果如下图所示:

 

G1垃圾回收器的它清理垃圾的步骤大致分为四步:

  1. 初始标记
  2. 并发标记
  3. 最终标记
  4. 复制回收

初始标记和并发标记和CMS的过程是差不多的,最后的筛选回收会首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划

因为采用的标记——整理的算法,所以不会产生内存碎片,最终的回收是STW的,所以也不会有浮动垃圾,Region的区域大小是固定的,所以回收Region的时间也是可控的

同时G1 使用了Remembered Set来避免全堆扫描,G1中每个Region都有一个与之对应的RememberedSet ,在各个 Region 上记录自家的对象被外面对象引用的情况。当进行内存回收时,在GC根节点的枚举范围中加入RememberedSet 即可保证不对全堆扫描也不会有遗漏。

以上就是CMS和G1的对比过程,如果面试中能回答出这些内容应该就能博得面试官一笑,盗图可耻,匿了

posted @ 2020-01-10 15:52  拂衣剑客  阅读(1793)  评论(3编辑  收藏  举报