JVM总结五:HotSpot几种垃圾收集器的奥秘
概要
HotSpot虚拟机提供了很多垃圾收集器,每个垃圾收集器都有自己的特点,在JVM的垃圾收集器来说,没有最好的垃圾收集器,只有最适合的垃圾收集器,在不同的情况使用不同的垃圾收集器,效率不一样。
在新生代:Serial垃圾收集器,ParNew垃圾收集器,Parallel Scavenge垃圾收集器
在老年代:Serial old垃圾收集器,Parallel old垃圾收集器,CMS垃圾收集器
通用并且目前最强:G1垃圾收集器。
新生代的垃圾收集器
Serial垃圾收集器
- 单线程:只开启一条GC回收线程,并且在回收过程中暂停一切用户线程,从而用户请求和图形界面会出现卡顿。
- 只适用于客户端应用:一般客户端应用所需的内存较小,不会创建太多对象,而且堆内存不大,因此垃圾回收时间比较短,即使在这段时间内停止一切用户线程,用户也不会感觉到卡顿,因此Serial垃圾收集器适合在客户端使用。
- 简单高效:由于Serial垃圾收集器只有一条GC回收线程,因此避免了一切切换的开销。
- 采用复制算法。
ParNew垃圾收集器
ParNew是Serial 的多线程版本
- 多线程并行执行:ParNew由多条GC线程并行的进行垃圾清理。但是清理过程仍然停止一切用户线程。但由于多条GC同时执行,清理速度比Serial收集器有所提高。
- 适合多CPU的服务器环境:多线程所有适用于多CPU环境。
- 与Serial性能对比:ParNew唯一的区别就是使用了多线程回垃圾,在多CPU环境比Serial收集器的效率要高,但是线程切换会需要额外的开销,故在单CPU环境中,Serial的表现比PraNew好。
- 采用复制算法。
- 追求 -降低停止等待时间:和Serial相比,ParNew使用多线程的目的就是缩短垃圾收集时间,从而减少用户等待时间。
Parallel Scavenge垃圾收集器
Parallel Scavenge和ParNew都是 使用多线程、新生代垃圾收集器、都使用的复制算法进行垃圾回收。但是他们有个不同:ParNew追求较少用户等待时间,Parallel Scavenger追求CPU最大吞吐量,能在较短时间完成任务,因此适合没有交互的后台计算。
- 吞吐量:指用户线程运行的时间占CPU总时间的比例,CPU总时间包括:用户线程运行时间和GC线程运行时间,故,吞吐量高表示用户线程运行时间越长,从而用户能够被快熟处理完。
- 降低停顿时间的两种方式:①在多CPU环境中使用多条GC线程,从而垃圾收集时间减少,用户停顿也减少。②实现GC线程与用户线程的并发执行。
- Parallel Scavenge参数:-XX:GCTimeRadio设置垃圾回收时间占总CPU时间的百分比;-XX:MaxGCPauseMillis设置垃圾处理过程最久停顿时间。
老年代垃圾收集器
Serial old垃圾收集器
Serial Old是Serial的老年代版本,都是使用单线程,都适用于客户端,唯一的区别使用的是 标记-整理算法。
Parallel Old垃圾收集器
Parallel Old收集器是Parallel Scavenge的老年代版本,一般它们搭配使用,追求CPU吞吐量。
它们在垃圾收集时都是由多条GC线程并行执行,并停止一切用户线程。因此,由于在垃圾清理过程中没有使垃圾收集和用户线程并行执行,因此它们是追求吞吐量的垃圾收集器。
CMS垃圾收集器
CMS收集器是在老年代中追求停顿时间的收集器,他在垃圾收集时与用户线程并发的执行,因此垃圾回收过程中用户不会觉得明显的卡顿。但是用户线程和GC线程的切换有开销,垃圾回收时间会被延长。
- 吞吐量低
- 无法处理浮动垃圾
- 使用标记清理算法产生内存碎片。
- 垃圾回收过程:①初始标记②并发标记③重新标记④并发清除
通用垃圾收集器G1垃圾收集器
目前最常用
G1特点
- 追求停顿时间
- 多线程GC
- 面向服务端应用
- 标记整理算法和复制算法合并,不会产生内存碎片
- 对整个堆进行垃圾回收
- 可预测停顿时间。
G1内存模型
G1中没有新生代和老年代的区别,将堆划分成一块块独立的Region。当进行垃圾收集时,估算Region的数量,每次从最大回收价值的Region开始回收,获得最大的回收率。
Remembered Set
每个Region都有一个Remembered Set,用于记录本区域中所有对象引用的对象所在的区域,从而在进行可达性分析时,只要在GC ROOTs中再加上Remembered Set即可防止对所有堆内存的遍历。
垃圾收集的过程
- 初始标记
- 并发标记
- 最终标记
- 帅选回收