Java虚拟机面试题 - Java中常见的垃圾收集器有哪些?
引言
Java的垃圾收集(GC)机制是JVM的核心功能之一,它自动管理内存分配与回收,极大减轻了开发者的负担。本文将详细介绍Java中常见的垃圾收集器,并通过流程图帮助理解它们的工作原理。
1. 垃圾收集器概述
Java虚拟机规范没有明确规定垃圾收集的实现方式,因此不同厂商、不同版本的JVM可能提供不同的垃圾收集器。HotSpot虚拟机作为最常用的JVM实现,提供了多种垃圾收集器,适用于不同的应用场景。
2. 常见垃圾收集器
2.1 Serial收集器
特点:
- 单线程工作,进行垃圾收集时必须暂停所有工作线程(Stop The World)
- 新生代采用复制算法
- 简单高效,适合客户端模式或小内存应用
适用场景:
- 单CPU环境
- 客户端应用
- 内存较小的嵌入式系统
2.2 ParNew收集器
特点:
- Serial收集器的多线程版本
- 新生代并行收集,老年代串行收集
- 与CMS收集器配合使用
适用场景:
- 多CPU服务器环境
- 需要与CMS收集器配合使用的场景
2.3 Parallel Scavenge收集器
特点:
- 新生代并行收集器
- 关注吞吐量(用户代码运行时间/(用户代码运行时间+GC时间))
- 提供自适应调节策略
适用场景:
- 后台运算不需要太多交互的任务
- 对吞吐量有较高要求的应用
2.4 Serial Old收集器
特点:
- Serial收集器的老年代版本
- 单线程工作,使用标记-整理算法
- 主要作为CMS收集器的后备预案
2.5 Parallel Old收集器
特点:
- Parallel Scavenge的老年代版本
- 多线程并行收集
- 使用标记-整理算法
适用场景:
- 与Parallel Scavenge配合使用
- 注重吞吐量的应用
2.6 CMS(Concurrent Mark Sweep)收集器
特点:
- 以获取最短回收停顿时间为目标
- 基于标记-清除算法
- 并发收集,减少停顿时间
工作流程:
适用场景:
- 重视响应速度的服务
- 老年代收集
- CPU资源较充足
缺点:
- 对CPU资源敏感
- 无法处理浮动垃圾
- 会产生内存碎片
2.7 G1(Garbage First)收集器
特点:
- 面向服务端应用的垃圾收集器
- 分Region的内存布局
- 可预测的停顿时间模型
- 整体基于标记-整理,局部基于复制算法
工作流程:
适用场景:
- 大内存多处理器机器
- 需要低延迟的应用
- JDK9及以后的默认收集器
2.8 ZGC收集器
特点:
- 低延迟垃圾收集器
- 停顿时间不超过10ms
- 处理TB级内存
- 基于Region内存布局
- 使用读屏障、染色指针等技术
适用场景:
- 超大堆内存应用
- 对延迟极其敏感的应用
2.9 Shenandoah收集器
特点:
- 低延迟垃圾收集器
- 与ZGC竞争
- 使用转发指针技术
- 并发压缩
适用场景:
- 类似ZGC,适用于大内存低延迟场景
3. 垃圾收集器组合
不同垃圾收集器可以组合使用:
4. 如何选择垃圾收集器
选择垃圾收集器时需要考虑以下因素:
-
应用特性:
- 吞吐量优先 vs 低延迟优先
- 内存大小
- 并发线程数
-
硬件环境:
- CPU核心数
- 内存带宽
-
JVM版本:
- 新版本JVM提供更多高级收集器
一般建议:
- 小型应用:Serial收集器
- 服务端应用:G1或ZGC
- 超大堆:ZGC或Shenandoah
- JDK8及以前:CMS或Parallel组合
5. 总结
Java提供了丰富的垃圾收集器选择,从简单的Serial收集器到先进的ZGC、Shenandoah,开发者可以根据应用需求选择合适的收集器。随着Java的发展,低延迟、大内存的收集器将成为主流,如G1已在JDK9+中成为默认收集器,ZGC和Shenandoah也在不断优化中。
理解不同垃圾收集器的工作原理和适用场景,有助于我们更好地调优Java应用性能,在内存管理和响应速度之间取得平衡。