Java 垃圾回收机制:G1、ZGC 调优实战
垃圾回收是 Java 的核心特性。本文介绍 GC 的原理和调优。
GC 基础
什么是垃圾回收?
自动释放不再使用的对象占用的内存。
如何判断对象已死?
- 引用计数:计数为 0 时回收(有循环引用问题)
- 可达性分析:从 GC Root 不可达时回收(Java 使用)
GC Root
- 虚拟机栈中的引用
- 方法区中的静态引用
- 方法区中的常量引用
- 本地方法栈中的引用
垃圾回收算法
1. 标记-清除
标记存活对象,清除未标记对象。
问题: 内存碎片
2. 标记-整理
标记存活对象,将存活对象向一端移动。
优点: 无碎片
3. 复制算法
将内存分为两块,每次使用一块,GC 时将存活对象复制到另一块。
优点: 无碎片,效率高
垃圾收集器
Serial
单线程收集器,适合客户端。
Parallel
多线程收集器,适合后台计算。
CMS
低停顿收集器,适合 Web 应用。
G1
分 Region 收集器,适合大内存。
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
ZGC
超低停顿收集器,停顿时间 < 1ms。
-XX:+UseZGC
-Xmx16g
GC 调优
1. 监控 GC
# 打印 GC 日志
-Xlog:gc*:file=gc.log
# 使用 jstat
jstat -gcutil <pid> 1000
2. 常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
| 频繁 Full GC | 内存不足 | 增加堆内存 |
| GC 停顿长 | 对象太多 | 优化代码 |
| 内存泄漏 | 引用未释放 | 检查代码 |
3. 调优参数
# 堆大小
-Xms4g -Xmx4g
# 新生代比例
-XX:NewRatio=2
# 晋升阈值
-XX:MaxTenuringThreshold=15
最佳实践
- 设置堆大小:-Xms 和 -Xmx 设为相同值
- 选择合适的收集器:根据应用场景选择
- 监控 GC 日志:定期分析 GC 日志
- 避免内存泄漏:检查资源释放
总结
GC 调优是 JVM 性能优化的重要环节。了解 GC 原理,选择合适的收集器,可以提升应用性能。