垃圾收集器是对应垃圾收集算法的具体实现,并且不同的垃圾收集器对应不同应用场景,会有不同的组合。
因此并不存在完美的垃圾收集器,需要通过了解垃圾收集器的特性与组合,才能在调优时选择最适合的收集器。
Serial 收集器
是最基本
、发展历史最悠久的收集器。(老古董?)
特点: 单线程的收集器
垃圾收集算法: 复制算法
优点: 简单而高效
,对于限定单个 CPU 环境来说,由于没有线程交互的开销,专心做垃圾收集从而获得最高的单线程收集效率。
缺点: 它进行垃圾收集时,必须暂停其他所有的工作线程(即 Stop The World)
,直到它收集结束。(用户体验很差)
应用场景: Serial
收集器对于运行在 Client 模式
下的虚拟机来说是一个很好的选择。
组合: Serial 收集器(新生代)
+ Serial Old 收集器(老年代)
ParNew 收集器
是 Serial 收集器
的多线程版本
,因此所有可用的参数,收集算法,Stop The World
,对象分片规则,回收策略都与 Serial 收集器一样
特点: 多线程收集器
垃圾收集算法: 复制算法
缺点: 它进行垃圾收集时,必须暂停其他所有的工作线程(即 Stop The World)
,直到它收集结束。(用户体验很差)
线程数: 默认开启的收集线程数与 CPU 数相同
VM 指令:
ParNew 收集器
ParNew 收集器
组合:
ParNew 收集器(新生代)
+ Serial Old 收集器(老年代)
ParNew 收集器(新生代)
+ CMS 收集器(老年代)
Parallel Scavenge 是一个新生代收集器,又叫吞吐量优先收集器
特点: 并行的多线程收集器,
这个收集器的目标准则是达到一个可控制的吞吐量
。
停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验;
而高吞吐量能高效的利用 CPU 时间,尽快的完成程序的运行任务,主要适合在后台运算而不需要太多交互的任务。
吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)
PS:虚拟机运行 100 分钟,其中垃圾回收用时 1 分钟,吞吐量就是 99%
垃圾收集算法: 复制算法
VM 指令:
应用场景: 注重高吞吐量,CPU 资源敏感的系统,比如大数据统计计算系统
组合:
Parallel Scavenge 收集器(新生代)
+ Serial Old 收集器(老年代)
JDK 1.6 之前,别无选择Parallel Scavenge 收集器(新生代)
+ Parallel Old 收集器(老年代)
JDK 1.6 开始Serial Old 收集器
是 Serial 收集器
的老年代版本,JDK 1.6 开始提供
特点: 单线程的收集器
垃圾收集算法: 标记-整理算法
优点: 简单而高效
,对于限定单个 CPU 环境来说,由于没有线程交互的开销,专心做垃圾收集从而获得最高的单线程收集效率。(同 Serial 收集器)
缺点: 它进行垃圾收集时,必须暂停其他所有的工作线程(即 Stop The World)
,直到它收集结束。(同 Serial 收集器)
应用场景:
Client 模式
下的虚拟机。(同 Serial 收集器)Server 模式下
,CMS 收集器
的后备方案,在并发发生 Concurrent Mode Failure
时使用。Server 模式下
,JDK 1.5 及以前版本中与 Parallel Scavenge 收集器
搭配使用。(也就是说现在不用了)组合: Serial 收集器(新生代)
+ Serial Old 收集器(老年代)
Parallel Old 收集器
是 Parallel Scavenge 收集器
的老年代版本
特点: 多线程收集器
。
垃圾收集算法: 标记-整理算法
应用场景: 注重高吞吐量,CPU 资源敏感的系统,比如大数据统计计算系统
组合: Parallel Scavenge 收集器(新生代)
+ Parallel Old 收集器(老年代)
CMS 收集器
是一种获取最短回收停顿时间为目标的收集器。考虑用于顶替 CMS 收集器
。
特点: 重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验
垃圾收集算法: 标记-清除算法
步骤:
GC Root
能直接关联的对象,速度很快GC Root Tracing
过程,与并发清除一同工作,耗时长优点: 并发收集,低停顿
。整个回收中,耗时最长的 并发标记 与 并发清除 都可以与用户线程并发运行
缺点:
占用一部分 CPU 资源,导致应用程序变慢,总吞吐量降低
。默认线程数是 (CPU 数量 + 3)/ 4,当 4 个 CPU 以上时,并发回收垃圾收集线程占用资源不小于 25%,随 CPU 数量增加而下降。CMS 收集器
无法处理浮动的垃圾 (标记阶段后又产生的垃圾,只能放下次 GC 回收),可能出现 Concurrent Mode Failure 导致 Full GC。Serial Old 收集器
进行老年代垃圾回收,停顿更久。标记-清除算法
实现的回收,因此 存在大量空间碎片的产生,会给大对象分配带来大麻烦VM 指令:
CMS 收集器
顶不住要进行 Full GC 时,开启内存碎片的合并整理过程。应用场景: Java 应用集中在互联网站或 B/S 系统的服务端上
组合: ParNew 收集器(新生代)
+ CMS 收集器(老年代)
G1 收集器是一款 面向服务端应用的垃圾收集器 ,JDK 1.7 中被视为最前沿的成果之一,JDK 1.9 默认垃圾收集器为 G1
特点:
G1 收集器
依然能通过并发的方式让 Java 代码继续运行。标记-整理
算法实现,不会产生空间内存碎片。Region 区域:
G1 将内存分为多个大小相等的独立区域 Region,虽然保留新生代,老年代的概念,但是已经不是物理上的隔离,他们都是一部分 Region(无需连续) 的集合。
G1 跟踪各个 Region 里面的垃圾堆积的价值大小,在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region
垃圾收集算法: 标记-整理算法
步骤:
GC Roots
能直接管理到的对象,并且修改 TAMS 的值,让下一阶段用户程序并发执行时,能在正确可用的 Region 中创建对象,需要停顿线程,耗时短。GC Roots
开始对堆中的对象,进行可达性分析,找出存活东西,这阶段耗时较长,可与用户程序并发执行。组合: G1 收集器
无需与其他收集器配合,能够 独立管理整个 GC 堆
JDK1.7 默认垃圾收集器:Parallel Scavenge(新生代)+ Parallel Old(老年代)
JDK1.8 默认垃圾收集器:Parallel Scavenge(新生代)+ Parallel Old(老年代)
JDK1.9 默认垃圾收集器:G1
纯属个人理解:
注重吞吐量系统:尽可能高效的利用 CPU 资源
ParNew 收集器(新生代)
+ CMS 收集器(老年代)
Parallel Scavenge 收集器(新生代)
+ Parallel Old 收集器(老年代)
一般 Java B/S 系统:注重快速响应,提升用户体验
ParNew 收集器(新生代)
+ CMS 收集器(老年代)
G1 收集器
垃圾回收统计信息
堆设置
收集器设置
并行收集器设置