0. 预备知识
0.1 Stop-the-World
- JVM 由于要执行 GC 而停止了程序的执行
- 这种情况会在任何一种 GC 算法中发生
- 多数 GC 优化通过减少 Stop-the-World 发生的时间来提高程序性能
0.2 Safepoint
在可达性分析中,将所有线程都停止,形成一个快照点 (Safepoint),保证了分析结果的确定性
- 产生 Safepoint 的地方:方法调用、循环跳转和异常跳转等
- Safepoint 数量要适中
0.3 JVM 运行模式
- Server
- Client
Server 启动较慢,但是启动之后的运行速度比 Client 更快
# 查看 JVM 使用哪种运行模式
$ java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
1. 常见垃圾收集器

1.1 年轻代中常见垃圾收集器
1.1.1 Serial 收集器
- 单线程收集,进行垃圾收集时,会暂停所有工作线程
# 指定 GC 使用 Serial (复制算法)
-XX: +UseSerialGC
1.1.2 ParNew 收集器
- 多线程收集,其余与 Serial 一致
- 单核执行效率不如 Serial,多核下有优势
# 指定 GC 使用 ParNew (复制算法)
-XX: +UseParNewGC
1.1.3 Parallel Scavenge 收集器
吞吐量 = 运行用户代码的时间 / (运行用户代码的时间 + 垃圾回收的时间)
- 与 ParNew 类似,都使用多线程
- Parallel Scavenge 相对于 ParNew 不同的是,后者更注意用户线程的等待时间,前者则是关注整个系统的吞吐量
- JVM Server 模式下默认
# 指定 GC 使用 Parallel Scavenge (复制算法)
-XX: +UseParallelGC
1.2 常见的老年代收集器
1.2.1 Serial Old 收集器
- 单线程收集,进行垃圾收集时,会暂停所有工作线程
- 简单高效,Client 模式下默认的老年代收集器
# 指定 GC 使用 Serial Old (标记-整理算法)
-XX: +UseSerialOldGC
1.2.2 Parallel Old 收集器
- 与 Parallel Scavenge 类似,只不过采用的是标记-整理算法
# 指定 GC 使用 Parallel Old (标记-整理算法)
-XX: +UseParallelOldGC
1.2.3 CMS 收集器
- 清理线程和用户线程几乎能做到同时工作
标记和回收过程 (六步)
- 初始标记:Stop-the-World
- 并发标记:并发追溯标记,程序不会停顿
- 并发预清理:查找执行并发标记阶段从年轻代晋升到老年代的对象
- 重新标记:暂停虚拟机 (Stop-the-World),扫描 CMS 堆中的剩余对象
- 并发清理:清理垃圾对象,程序不会停顿
- 并发重置:重置 CMS 收集器的数据结构
# 指定 GC 使用 CMS (标记-清除算法)
-XX: +UseConcMarkSweepGC
1.3 年轻代和老年代公用的算法
1.3.1 G1 收集器
- 并发和并行
- 分代收集
- 空间整合(标记-整理)
- 可预测的停顿(指定在 M 毫秒内,消耗在 GC 上的时间不得超过 N 毫秒)
工作原理简述
- 将 Java 堆内存划分成多个大小相等的 Region
- 上面的特性导致了,新生代和老年代不再是物理隔离的内存空间,他们现在都是一系列 Region 的集合,在逻辑上连续
# 指定 GC 使用 G1 (复制 + 标记-清除算法)
-XX: +UseG1GC