java -XX:+PrintFlagsFinal -version | grep ‘:=’
可以看到1.8默认的是 UseParallelGC
在JVM中是+XX配置实现的搭配组合:
UseSerialGC 表示 “Serial” + “Serial Old”组合
Serial/Serial Old收集器 是最基本最古老的收集器,它是一个单线程收集器,并且在它进行垃圾收集时,必须暂停所有用户线程。Serial收集器是针对新生代的收集器,采用的是Copying算法,Serial Old收集器是针对老年代的收集器,采用的是Mark-Compact算法。它的优点是实现简单高效,但是缺点是会给用户带来停顿。
UseParNewGC 表示 “ParNew” + “Serial Old”
ParNew收集器 是Serial收集器的多线程版本,使用多个线程进行垃圾收集。
UseConcMarkSweepGC 表示 “ParNew” + “CMS”. 组合,“CMS” 是针对旧生代使用最多的
CMS(Concurrent Mark Sweep)收集器 是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。
年轻带只能配合Parallel New或Serial回收器
UseParallelGC 表示 “Parallel Scavenge” + “Parallel Old”组合
Parallel Scavenge收集器 是一个新生代的多线程收集器(并行收集器),它在回收期间不需要暂停其他用户线程,其采用的是Copying算法,该收集器与前两个收集器有所不同,它主要是为了达到一个可控的吞吐量。
Parallel Old收集器 是Parallel Scavenge收集器的老年代版本(并行收集器),使用多线程和Mark-Compact算法。
在实践中使用UseConcMarkSweepGC 表示 “ParNew” + “CMS” 的组合是经常使用的
CMS(Concurrent Mark Sweep),我们可以轻易地从命名上看出,它是一个并发的,然后是基于标记——清理的垃圾回收器,它清理垃圾的步骤大致分为四步:
初始标记
并发标记
重新标记
并发清理
初始标记只要是找到GC Roots,所以是一个很快的过程,并发标记和用户线程一起,通过GC Roots找到存活的对象,重新标记主要是修复在并发标记阶段的发生了改变的对象,这个阶段会Stop the World;
并发清理则是保留上一步骤标记出的存活对象,清理掉其他对象,正因为采用并发清理,所以在清理的过程中用户线程又会产生垃圾,而导致浮动垃圾,只能通过下次垃圾回收进行处理;
因为cms采用的是标记清理,所以会导致内存空间不连续,从而产生内存碎片
扩展:G1(Garbage-First),以分而治之的思想将堆内存分为若干个等大的Region块,虽然还是保留了新生代,老年代的概念,但是G1主要是以Region为单位进行垃圾回收
G1垃圾回收器的它清理垃圾的步骤大致分为四步:
初始标记
并发标记
最终标记
复制回收
初始标记和并发标记和CMS的过程是差不多的,最后的筛选回收会首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划
优点:1、因为采用的标记——整理的算法。所以不会产生内存碎片
2、最终的回收是STW的,所以也不会有浮动垃圾
3、Region的区域大小是固定的,所以回收Region的时间也是可控的
同时G1 使用了Remembered Set来避免全堆扫描,G1中每个Region都有一个与之对应的RememberedSet ,在各个 Region 上记录自家的对象被外面对象引用的情况。当进行内存回收时,在GC根节点的枚举范围中加入RememberedSet 即可保证不对全堆扫描也不会有遗漏。