恶土小队免安装绿色中文版
7.52G · 2025-11-04
很多人以为“调优 = 调 -Xmx”,这是最表层的理解。
真正完整的调优包含四层:
| 层级 | 调整内容 | 目标 | 工具/参数 |
|---|---|---|---|
| 第一层:空间结构 | 新生代/老年代大小、Survivor 比例 | 控制对象流动节奏,避免过早晋升或空间浪费 | -Xmn, -XX:NewRatio, -XX:SurvivorRatio |
| 第二层:晋升策略 | 对象在新生代“熬”几次 GC 才进老年代 | 过滤短命对象,减轻老年代压力 | -XX:MaxTenuringThreshold, -XX:+UseAdaptiveSizePolicy |
| 第三层:GC算法 | 选择 Serial / Parallel / G1 / ZGC | 匹配业务对“延迟”或“吞吐”的需求 | -XX:+UseG1GC, -XX:+UseZGC |
| 第四层:行为目标 | 设定最大停顿时间、Region大小、回收粒度 | 精细化控制 GC 行为,逼近业务 SLA | -XX:MaxGCPauseMillis, -XX:G1HeapRegionSize |
-Xms4g -Xmx4g -Xmn512m # 新生代仅 512M
→ Eden 秒满,每秒多次 Minor GC;
→ 虽单次快,但累积 STW 时间长,CPU 被 GC 线程吃满;
→ Survivor 放不下存活对象,大量短命对象提前晋升老年代。
-Xmn3g -Xmx4g # 老年代只剩 1G
→ 缓存、连接池、大对象稍多就撑满;
→ Full GC 触发,STW 1~5 秒,用户请求超时;
→ 如果用 CMS,还会触发 Concurrent Mode Failure,更卡。
-XX:MaxTenuringThreshold=1 # 活一次就进老年代
→ 本该在新生代死的对象,全跑老年代去了;
→ Full GC 时要扫描/移动这些“垃圾”,效率极低;
→ Full GC 时间变长,频率变高。
算法思想相同,但“执行引擎”不同 —— 这才是核心差异。
| 场景 | 错误选择 | 后果 | 正确选择 |
|---|---|---|---|
| 高并发 Web 服务 | 用 Serial GC | 单线程 STW,每次 GC 全服务卡住 | G1 / ZGC(并发、低停顿) |
| 大数据批处理 | 用 CMS | 碎片多 + Full GC 频繁,总耗时更长 | Parallel GC(吞吐优先) |
| 大堆低延迟 | 用 Parallel GC | STW 太长,无法满足 SLA | ZGC / Shenandoah(亚毫秒停顿) |
不调优 = 让 JVM 用“猜的策略”硬扛你的业务 → 轻则性能差,重则 OOM 崩溃。
必须监控的核心指标:
| 指标 | 工具 | 说明 |
|---|---|---|
| Minor GC 频率 & 耗时 | jstat -gc <pid> | 频繁 or 耗时长 → 调新生代大小 or GC 算法 |
| Full GC 频率 & 耗时 | jstat -gc <pid> | 频繁 → 老年代太小 or 晋升太快 or GC 算法错 |
| 老年代使用率曲线 | Grafana / VisualVM | 是否平稳?还是阶梯式暴涨? |
| 每次 GC 后老年代回收率 | GC 日志 | 回收率低 → 老年代全是“真长期对象” or 被短命对象污染 |
示例 jstat:
S0C S1C S0U S1U EC EU OC OU YGC YGCT FGC FGCT
10752.0 10752.0 0.0 8960.0 65536.0 65536.0 175104.0 174890.1 123 2.452 5 8.732
→ EU 满 → 触发 YGC;OU 接近 OC → 危险,快 Full GC。
-Xmn2g # 总堆 4G 时,新生代占一半
-XX:NewRatio=3 # 老年代 : 新生代 = 3:1
-XX:SurvivorRatio=6 # Eden:S0:S1 = 6:1:1 (默认 8:1:1)
-XX:MaxTenuringThreshold=20 # 默认 15,可适当调高
| 业务类型 | 推荐 GC | 关键参数 | 理由 |
|---|---|---|---|
| 高并发 Web / API | G1GC | -XX:MaxGCPauseMillis=100 | 可控停顿,Region 回收,适合大堆低延迟 |
| 大数据批处理 | Parallel GC | 无特殊参数 | 最大吞吐量,STW 长但总时间短 |
| 超大堆 + 极致低延迟 | ZGC | -XX:+UseZGC -Xmx32g | 亚毫秒停顿,适合 >16G 堆 |
| 客户端 / 小应用 | Serial GC | 无 | 单线程,开销小,适合 <4G 堆 |
调完必须验证:
工具:
jstat -gcutil <pid> 1000:实时看 GC 利用率;jmap -histo:live <pid>:看存活对象类型分布;开启 GC 日志(必备):
-Xloggc:/logs/gc.log
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintTenuringDistribution # 看对象年龄分布,关键!
| 错误做法 | 后果 | 正确做法 |
|---|---|---|
| 只调 -Xmx,不调 -Xmn | 新生代比例失调,GC 更频繁 | 同步调整新生代大小,保持合理比例 |
| SurvivorRatio 设太小(如 2) | Survivor 太小,对象秒晋升 | 保持默认 8 或微调到 6~7 |
| MaxTenuringThreshold 设 0 或 1 | 对象“秒进”老年代,污染严重 | 至少设 5 以上,观察年龄分布后再调 |
| 业务敏感还用 Parallel GC | STW 太长,请求超时 | 换 G1 或 ZGC,设 MaxGCPauseMillis |
| 不看 GC 日志,盲目调参 | 调了也不知道有没有用 | 必须开启 GC 日志,用工具对比验证 |
2025-11-04
兆易创新推出 GD32F503/505 系列 MCU 芯片:采用 Arm Cortex-M33 内核,12 月起量产供货
2025-11-04
三星 Galaxy S26 标准版被曝厚 6.96 毫米,手机壳渲染图曝光