jvm调优你会关注哪些字段?

1 个回答

  • 伏夕
    做你想做的,错了算我的。
    JVM 调优不是背参数表,而是围绕 **暂停/吞吐** 两个目标,盯住 **堆与分配画像、晋升与老年代、GC 暂停与原因、Safepoint、元空间/代码缓存** 这些核心字段,用 jcmd/jstat/JFR/GC 日志把“现象→字段→调整”闭环跑通。 分两类:**业务 K P I**(你真正要达成的目标)和**JVM/GC 侧可调与可观测字段**。 # 0)先定目标(两种典型 KPI) * **低延迟型**:P99/P999 延迟、Max STW 暂停、抖动(Jitter) * **吞吐型**:应用吞吐(req/s 或批处理速率)、CPU 利用率、GC 开销占比(<5–10%) # 1)可配置字段(JVM 启动参数) **堆与代区** * `-Xms/-Xmx`:堆初始/最大。建议**相等**避免扩容抖动。 * `-XX:MaxGCPauseMillis`(G1/ZGC)/ `-XX:GCTimeRatio`(吞吐目标) * 新生代大小:`-XX:NewRatio` 或 `-XX:NewSize`/`-XX:MaxNewSize`(Parallel/Serial/CMS) * Survivor:`-XX:SurvivorRatio`、`-XX:TargetSurvivorRatio` * 晋升阈值:`-XX:MaxTenuringThreshold` **元空间/代码缓存** * `-XX:MetaspaceSize` / `-XX:MaxMetaspaceSize` * `-XX:ReservedCodeCacheSize`(JIT 代码缓存,满了会降级编译) **GC 算法选择** * G1:`-XX:+UseG1GC`(默认 17+) * `-XX:InitiatingHeapOccupancyPercent`(IHOP,触发并发标记的老年代占用阈值) * `-XX:ConcGCThreads`、`-XX:ParallelGCThreads` * `-XX:+UseStringDeduplication`(需要评估 CPU) * ZGC:`-XX:+UseZGC`(低停顿) * `-XX:ZUncommitDelay`, `-XX:SoftMaxHeapSize` * Shenandoah:`-XX:+UseShenandoahGC`(低停顿) **容器与内存隔离** * `-XX:+UseContainerSupport`(JDK 10+ 默认),`-XX:MaxRAMPercentage`、`-XX:InitialRAMPercentage` * 关闭/开启压缩指针:`-XX:+UseCompressedOops`(<32GB 堆通常开启) # 2)运行期关键指标(要“持续采样/观测”的字段) **GC 频率与耗时** * **Young/Mixed/Full 次数、平均/最大暂停** * GC 开销占比:`GC Time / Process CPU Time` **内存画像** * **Allocation Rate**(对象分配速率,MB/s) * **Live Set / Old Gen 占用**(并发标记后仍存活的数据量) * **Promotion Rate**(晋升速率)与 **Survivor 利用率** * **Humongous 对象**(G1 > 1/2 region 的分配与回收情况) **并发阶段健康度** * G1:并发标记时间、Remembered Set(RSet)开销、Evacuation Failures * ZGC:并发阶段时间、Relocation set、Remapped pages **Safepoint/停顿** * 停顿原因(GC、Deopt、Biased Lock revoke 等) * **总 Safepoint 时间**与**时间分布**(是否有长尾) **元空间/代码缓存** * Metaspace 用量增长曲线、Code Cache 占用(接近满 => JIT 降级、抖动) **JIT/编译** * 编译时间、分层编译(Tiered)命中、**Deoptimization** 次数/原因 **线程与锁** * 活动线程数、可运行线程(runnable)对比 CPU 核数 * 锁竞争/阻塞(监控同步热点、偏向锁撤销、轻重锁膨胀) # 3)问题定位常用命令(现场可用) **即时诊断(JDK 自带)** ```bash jcmd <pid> VM.flags # 当前生效的 JVM 参数 jcmd <pid> GC.heap_info # 堆/代区信息 jcmd <pid> GC.class_histogram # 类实例分布(Top N 占用) jcmd <pid> GC.run # 触发一次 GC(慎用) jcmd <pid> GC.heap_dump filename=hprof # 导出堆 jcmd <pid> VM.native_memory summary # NMT 汇总(需 -XX:NativeMemoryTracking=summary/detail) jstat -gcutil <pid> 1000 # 每秒打印 GC 各区使用率 jstat -gccause <pid> 1000 # 最近 GC 原因 jstack <pid> # 线程栈(死锁/阻塞) ``` **JFR/剖析** * `jcmd <pid> JFR.start name=profile settings=profile filename=app.jfr duration=60s` * 分析:GC 暂停、对象分配热点、锁争用、I/O、CPU Hot Methods **GC 日志(JDK 9+ 统一日志)** ```bash -Xlog:gc*,safepoint,class+load=info:file=gc.log:tags,uptime,time,level ``` 关注日志里的:**Pause (Young/Mixed) 时间**、**Evacuation/Promotion 量**、**Humongous 分配**、**cause**、**User/Sync/Real** 时间对齐应用 KPI。 # 4)不同 GC 的“要看字段” **G1** * Region 大小(自动/`-XX:G1HeapRegionSize`) * Young/Mixed 比例与节奏、`IHOP` 动态/静态设置 * RSet 更新/扫描耗时、`Evacuation Failure`(一旦出现会有长停顿) * Humongous 区块数量与回收节奏(频繁大对象 → 代码与数据结构优化) **ZGC** * Max/Avg Pause(应在数毫秒级) * 并发阶段时间(Mark/Relocate/Remap) * `SoftMaxHeapSize` 与实际堆波峰/波谷 * 高分配速率下的 **relocation 进度滞后** # 5)阈值参考(经验值,按场景微调) * **Young GC 平均暂停**:< 50ms(低延迟),< 150ms(普通在线) * **Max STW**:低延迟 < 200ms;若有长尾需排查对象爆量/晋升失败 * **GC 开销**:总 CPU 时间的 < 5–10% * **Allocation Rate**:稳定、与业务吞吐成正比;尖刺伴随暂停 ↑ 需剖析分配热点 * **Old Gen 利用率**:相对稳定,无缓慢爬升(否则有内存泄漏风险) # 6)调优套路(顺序) 1. **确认目标**(低延迟/吞吐),选 GC(G1/ZGC)。 2. 定堆:`-Xms=-Xmx`,给到容器内存 60–70%(还要给 Metaspace/线程栈/OS)。 3. 设目标:G1 用 `-XX:MaxGCPauseMillis=200` 起步;观察 IHOP 与 Mixed 周期。 4. 观测:开 GC 统一日志 + jstat/jfr,看 **暂停/分配/晋升/老年代** 曲线。 5. 针对性调整: * 暂停长 → 增堆或放宽 MaxGCPauseMillis;降低晋升(调 Survivor/阈值);消除 Humongous * Full/混合频繁 → 降 IHOP(或改动态)、控制老年代增长(对象存活期/缓存) * Metaspace/CodeCache 告急 → 提高上限或减少动态生成类/反射代理 6. 代码层配合:减少临时对象、复用缓冲、优化热路径集合类型(避免装箱/复制)、减少大对象。
    发布于 2025-08-13 07:09 •IP属地 天津
    举报
    评论
    收藏