1. JVM 调优基础
- 目的: 减轻开发对内存管理的负担,优化是性能问题解决方案之一。
- 前提: 优先考虑代码逻辑、设计方案和中间件瓶颈。
2. JVM 内存模型
- 关键区域: 堆、方法区、程序计数器、虚拟机栈、本地方法栈。
- 堆内存: 分为年轻代(E区、S1区、S2区)和老年代。
3. 对象生命周期
.java
编译成.class
。- 类加载到JVM元空间。
- 对象在年轻代E区分配。
- 经历YGC后,存活对象移动到S区,多次后晋升老年代。
- 无引用对象在GC时回收。
4. 年轻代回收原理
- YGC触发: E区满触发,存活对象移至S0,E区垃圾回收。
- Stop the World: YGC期间系统暂停,不允许新对象创建。
5. 对象晋升老年代的条件
- 年龄: 默认躲过15次YGC,可通过
-XX:MaxTenuringThreshold
设置。 - 动态对象年龄判断: 超过S区一半容量的对象将晋升。
- 大对象: 超过
-XX:PretenureSizeThreshold
直接分配老年代。 - 临时晋升: S区不足时,直接晋升老年代。
6. 老年代 GC 触发时机
- Serial Old/Parallel Old: 老年代空间不足。
- CMS: 老年代使用达阈值(默认68%)。
- G1: 老年代区域使用率达阈值(默认45%)。
7. JVM 优化调优目标
- 低延迟: GC停顿时间短。
- 高吞吐量: 单位时间处理更多工作量。
- 大内存: 支持更大内存分配。
8. 目标权衡
- Web应用和微服务: 低延迟优先,推荐G1或ZGC/Sheanodah。
- 大数据处理和科学计算: 高吞吐量优先,推荐Parallel GC。
- 大型内存应用: 大内存管理优先,推荐G1 GC或ZGC。
9. JVM 优化场景
- 新应用上线: 压测,观察GC情况。
- 老应用: 监控反馈,优化内存异常。
10. 内存异常处理
- 堆内存溢出: 控制流量,扩容,限流。
- 内存泄漏: 分析dump文件,代码审查。
- 元空间溢出: 调大
-XX:MaxMetaspaceSize
,分析重复类。 - 栈溢出: 设置栈大小
-Xss
,控制线程数量。 - 直接内存溢出: 检查Direct ByteBuffer使用,调整
-XX:MaxDirectMemorySize
。
11. 监控指标
- YGC与FGC频率和耗时。
- YGC后存活对象数。
- 老年代对象增长速率。
12. 总结
- 好的JVM优化: YGC后存活对象小于S区50%,减少FGC频率。
- 监控重要性: 发现并及时排查问题。
- 实战经验: 增强对JVM和应用的理解与信心。