启动参数应说明资源预算和诊断证据,而不是复制一份几十行“万能调优参数”。本教程给出一个最小模板,并教你验证 JVM 实际采用了什么值。
Table of contents
使用最小启动模板
下面模板适合在预生产验证,具体数值必须由容器限制和压测决定:
java \
-XX:MaxRAMPercentage=70 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/diagnostics \
-Xlog:gc*,safepoint:file=/logs/gc.log:time,uptime,level,tags:filecount=5,filesize=20m \
-XX:StartFlightRecording=name=continuous,settings=default,maxage=2h,maxsize=512m,dumponexit=true,filename=/diagnostics/app.jfr \
-jar app.jar
不要同时设置固定 -Xmx 和 MaxRAMPercentage 后猜哪个生效。团队应选择一种堆预算方式,并在启动时输出最终值。
给非堆内存留空间
容器内存不只包含 Java 堆,还包含元空间、Code Cache、线程栈、直接缓冲区、JIT/GC 原生结构、共享库和 Native 分配。
若容器限制是 1 GiB,直接设置 -Xmx1g 很可能被操作系统 OOM Killer 终止,JVM 来不及生成 Heap Dump。
容量估算应满足:
容器上限 > Java 堆 + 元空间 + 线程栈 + 直接内存 + JVM Native + 安全余量
线程数增长会同时增加栈和调度开销。不要通过盲目减小 -Xss 掩盖无限制线程创建。
验证容器识别结果
在容器内运行:
java -XshowSettings:system -XshowSettings:vm -version
java -XX:+PrintFlagsFinal -version | grep -E 'MaxHeapSize|ActiveProcessorCount|Use.*GC'
检查 JVM 识别的 CPU、物理内存、最大堆和收集器。若平台限制与 JVM 输出不一致,先检查 JDK 补丁版本、cgroup 版本和
容器配置,再考虑手工设置 ActiveProcessorCount。
让日志可轮转、可归属
统一日志 -Xlog 支持标签、级别、时间和轮转。文件名或日志目录应能归属实例,持久卷要有容量与清理策略。Heap Dump
可能接近堆大小,写入时还会造成停顿;磁盘空间不足会让最需要的证据丢失。
敏感数据可能出现在 Heap Dump、线程栈、JFR 字段和命令行参数中。限制诊断目录权限,不把密码放在 JVM 参数里,导出 证据前执行脱敏和访问审批。
启动时审计参数
保存这些信息:完整 JDK 版本、镜像摘要、启动命令、最终 Flags、容器资源、部署版本和时间。遇到性能回归时,参数差异 比“代码没改”更有解释力。
下一步
阅读jcmd、JFR、VisualVM 与 async-profiler,用同一故障比较 不同证据工具。