在 JVM 参数中:
export JAVA_MEM_OPTS="-server -Xms4096m -Xmx4096m -Xmn1024m -XX:SurvivorRatio=18 -XX:+UseConcMarkSweepGC -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:CompressedClassSpaceSize=128m -Ddubbo.protocol.threads=300 -XX:CICompilerCount=4 -XX:ReservedCodeCacheSize=256m -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/dev/shm/gc-collection_system_javap.log"
-XX:SurvivorRatio=18
1. SurvivorRatio=18 的含义
SurvivorRatio控制 Eden 区与 Survivor 区的大小比例。SurvivorRatio=18表示:- Eden 区占年轻代(Young Generation)的
18/(18+2) = 90% - 每个 Survivor 区占
5%(两个 Survivor 区合计 10%)
- Eden 区占年轻代(Young Generation)的
2. 潜在问题分析
(1) Survivor 区过小
- 问题:Survivor 区仅占年轻代的 10%,可能导致:
- 短命对象直接晋升到老年代:当 Survivor 区无法容纳存活对象时,对象会提前晋升到老年代,增加 Full GC 频率。
- 内存浪费:Survivor 区过小可能导致 Eden 区的存活对象无法被有效复制,触发频繁的 Young GC 或 Full GC。
(2) Full GC 频繁
- 原因:
- Survivor 区过小 → 对象快速晋升到老年代 → 老年代快速填满 → 触发 Full GC(CMS)。
- CMS(Concurrent Mark Sweep)虽然低延迟,但频繁 Full GC 仍会导致应用暂停和性能抖动。
(3) 系统过载风险
- 高吞吐量场景:若应用生成大量短命对象,Survivor 区过小会导致对象快速晋升到老年代,触发频繁 Full GC,增加 CPU 和内存压力。
- GC 停顿时间增加:Full GC 的停顿时间通常比 Young GC 长,频繁 Full GC 可能导致系统响应变慢。
3. 优化建议
(1) 调整 SurvivorRatio
- 推荐值:
SurvivorRatio=4~8SurvivorRatio=4→ Eden 占 80%,每个 Survivor 占 10%SurvivorRatio=8→ Eden 占 89%,每个 Survivor 占 5.5%
- 示例修改:
-XX:SurvivorRatio=4
(2) 监控 GC 日志
-
启用 GC 日志分析:
-Xloggc:/path/to/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -
使用工具分析日志:
- GCViewer、GCEasy、JVisualVM 等工具分析对象晋升速率和 GC 行为。
(3) 调整年轻代大小
- 当前
Xmn=1024m(年轻代总大小):- 若 Survivor 区调整为 10%(100MB),可能仍不足。
- 建议:根据对象生命周期调整
Xmn,例如:-Xms4096m -Xmx4096m -Xmn2048m
(4) 考虑更换垃圾回收器
- CMS 已被弃用(JDK8 开始逐步淘汰):
-
推荐迁移至 G1(Garbage-First):
-XX:+UseG1GC -
G1 的优势:
- 自动平衡 Eden、Survivor 和老年代大小。
- 更适合大堆内存(>4GB)和低延迟场景。
-
4. 典型调优方案
(1) 短期优化(保留 CMS)
# 调整 SurvivorRatio 和 Xmn
export JAVA_MEM_OPTS="-server -Xms4096m -Xmx4096m -Xmn2048m \
-XX:SurvivorRatio=4 \
-XX:+UseConcMarkSweepGC \
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m \
-XX:CompressedClassSpaceSize=128m \
-XX:CICompilerCount=4 -XX:ReservedCodeCacheSize=256m \
-XX:+PrintGCDateStamps -XX:+PrintGCDetails \
-Xloggc:/dev/shm/gc-collection_system_javap.log"
(2) 长期优化(迁移到 G1)
# 使用 G1 垃圾回收器
export JAVA_MEM_OPTS="-server -Xms4096m -Xmx4096m -Xmn2048m \
-XX:SurvivorRatio=4 \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1HeapRegionSize=4M \
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m \
-XX:CompressedClassSpaceSize=128m \
-XX:CICompilerCount=4 -XX:ReservedCodeCacheSize=256m \
-XX:+PrintGCDateStamps -XX:+PrintGCDetails \
-Xloggc:/dev/shm/gc-collection_system_javap.log"
5. 验证步骤
- 监控 GC 日志:
- 观察
Full GC频率和耗时。 - 检查对象晋升速率(Promotion Rate)。
- 观察
- 调整后对比:
- 将
SurvivorRatio从18调整为4~8,观察 Full GC 减少情况。
- 将
- 使用 G1 测试:
- 替换为
-XX:+UseG1GC,对比 GC 吞吐量和延迟。
- 替换为
6. 总结
| 参数 | 当前值 | 问题 | 建议值 |
|---|---|---|---|
-XX:SurvivorRatio | 18 | Survivor 区过小,对象快速晋升到老年代 | 4~8 |
-XX:+UseConcMarkSweepGC | 使用 CMS | CMS 已弃用,性能不稳定 | -XX:+UseG1GC |
-Xmn | 1024m | 年轻代过小,Survivor 区不足 | 2048m |
结论:SurvivorRatio=18 确实可能导致频繁 Full GC 和系统过载,建议调整为 4~8 并考虑迁移到 G1 回收器。

2万+

被折叠的 条评论
为什么被折叠?



