HotSpot 垃圾收集器
hotspot虚拟机提供了多种垃圾收集器,每种垃圾收集器都有各自的特点。
新生代垃圾收集器
Serial垃圾收集器(单线程)
只开启一条GC线程进行垃圾回收,并且垃圾回收过程停止一切用户进程,即stop The World。
一般客户端应用所需要的内存较小,不会创建太多对象,而且堆内存不大,因此垃圾收集时间短,即使在这段时间内停止一切用户线程,也不会感觉到明显的卡顿。
由于Serial只使用一条GC,避免了线程切换所造成的开销简单高效
ParNew垃圾收集器(多线程)
ParNew 是serial 的多线程版本,由多条GC线程进行垃圾收集,在多cpu环境先比serial会有一定的提升;但线程切换需要额外的开销,因此在但cpu的环境中不如serial。
Parallel Scavenge垃圾收集器(多线程)
parallel Scavenge 和parNew都是多线程、新生代垃圾收集器。但是两者有着巨大的不同
- Parallel Scavenge 追求CPU的吞吐量,能够在较短的时间内完成指定的任务,因此适合没有交互的后台计算
- ParNew 追求降低用户停顿时间,适合交互式应用
追求吞吐量,可以通过减少GC执行实际工作时间,然而,仅仅偶尔运行GC意味着当CG运行的时候,这时候已经积累了很多对象内存,提高单次工作量,导致有更高的暂停时间。而考虑到底暂停,这时候要频繁的运行GC,反过来导致吞吐量下降。
- 通过参数 -XX:GCTimeRadio 设置垃圾回收时间占总cpu的百分比
- 通过参数 -XX:MaxGCPauseMillis 设置垃圾处理时间最久停顿多久
- 通过命令 -XX:+UseAdaptiveSizePolicy 开启自适应策略。只要我们设置好堆的大小和MaxGCPauseMillis或者GCTimeRadio,收集器会自动调整新生代的大小、Eden和Survivor的比例、对象进入老年代的年龄、以最大程度上接近我们设置的MaxGCPauseMillis或者GCTimeRadio。
老年代收集器
serial old 垃圾收集器
与新生代的serial 一致,但是老年代使用的是“标记-整理算法”,新生代使用的是“复制算法”
Parallel Old 垃圾收集器
Parallel old是Parallel Scavenge的老年代版本,追求cpu的吞吐量。
CMS垃圾收集器
CMS是并发标记清除,以停顿时间最短为目标的收集器,垃圾收集时,GC线程和用户线程并发执行,不感到明显的卡顿。
- 初始标记 Stop The World,仅一条线程初始化标记对CG Roots 直接关联的对象标记
- 并发标记 使用多条线程,与用户现场并发执行,标记出废弃的对象,速度慢
- 重新标记 Stop The World,使用多条标记线程并发执行,将刚才并发标记过程中新出现的废弃对象标记出来
- 并发清除 只使用一条GC线程,与用户线程并发执行,清除刚才标记的对象。耗时
耗时最长的并发标记和并发清除与用户线程一起并发, 所以CMS是与用户线程一起并发的
CMS缺点:
- 吞吐量低
- 无法处理浮动垃圾
- 使用标记-清除法产生碎片空间,导致频繁 FullGC
对于产生的碎片空间的问题,可以通过开启-XX:+UseCMSCompactAtFullCollection,在每次Full GC完成后都会将零散在各处的对象整理到一块。设置参数 -XX:CMSFullGCsBeforeCompaction告诉CMS,经历N次Full GC之后再进行一次内存整理。
G1通用垃圾收集器
G1 没有新生代和老年代的概念,它将堆内存划分为一块块独立的区域,当要进行垃圾回收的时候,会计算每个区域的垃圾数量,每次都从回收价值最大的区域中回收,获得最大的回收效率。整体来看,G1是基于标记清除算法,从每个区域之间是基于复制算法的。
G1 清除对象会带上区域标记。所以不会清除掉其他区域。(对象跨区域的情况)
- 初始化标记
- 并发标记
- 最终标记
- 筛选回收