请列举你熟悉的常用 JVM 启动和调优参数(如 -Xms, -Xmx, -Xmn, -XX:SurvivorRatio, -XX:+HeapDumpOnOutOfMemoryError 等)的作用。
JVM(Java虚拟机)的启动和调优参数非常多,合理配置这些参数对于提升应用的性能、吞吐量以及排查线上问题至关重要。
为了便于记忆和理解,我将常用参数分为 内存管理、垃圾回收器(GC)配置、GC日志与诊断、OOM异常处理 以及 高级性能调优 五大类进行详细列举和解释:
一、 堆内存与元空间设置(基础内存管理)
这是最常用的参数,用于规定 JVM 的内存边界。
-Xms<size>:设置初始堆内存大小(如-Xms2g)。- 最佳实践:生产环境中通常将
-Xms和-Xmx设置为相同的值,以避免应用运行期间堆内存频繁扩容和缩容带来的性能开销。
- 最佳实践:生产环境中通常将
-Xmx<size>:设置最大堆内存大小(如-Xmx2g)。一旦堆内存超过此值,就会抛出OutOfMemoryError: Java heap space。-Xmn<size>:设置年轻代(Young Generation)大小。年轻代过大会导致老年代变小,过小会导致频繁的 Minor GC。-Xss<size>:设置每个线程的栈大小(如-Xss1m)。决定了方法调用的深度。如果应用有极深的递归,可能需要调大;如果并发线程数极大,为了防止 OOM,可能需要调小(默认通常是 1MB)。-XX:MetaspaceSize=<size>(Java 8+):初始元空间大小。这是触发第一次元空间 GC 的高水位线,设置得当可以避免启动时频繁触发 Full GC。-XX:MaxMetaspaceSize=<size>(Java 8+):最大元空间大小。限制类加载器元数据的内存占用,防止由于内存泄漏(如动态生成过多类)耗尽物理内存。
二、 堆内存比例调整(精细化调优)
用于控制堆内各个区域的比例,影响对象的晋升和 GC 频率。
-XX:SurvivorRatio=N:设置年轻代中 Eden 区与单个 Survivor 区的比例。- 示例:
-XX:SurvivorRatio=8(默认值),表示Eden : Survivor0 : Survivor1 = 8 : 1 : 1。Eden 区占年轻代的 8/10。
- 示例:
-XX:NewRatio=N:设置 老年代与年轻代的比例。- 示例:
-XX:NewRatio=2(默认值),表示老年代 : 年轻代 = 2 : 1,即年轻代占整个堆的 1/3。
- 示例:
-XX:MaxTenuringThreshold=N:设置对象晋升老年代的年龄阈值。- 对象每熬过一次 Minor GC,年龄加 1。最大值为 15(因为对象头中记录年龄的只有 4 bit)。如果设置为 0,对象直接进入老年代。
三、 OOM 故障诊断(救命参数)
生产环境必配参数,用于在程序崩溃时保留现场。
-XX:+HeapDumpOnOutOfMemoryError:当发生 OOM 时,自动生成 Heap Dump(堆转储)文件。这是排查内存泄漏的最重要文件。-XX:HeapDumpPath=<path>:指定 Dump 文件的保存路径。- 示例:
-XX:HeapDumpPath=/data/logs/heapdump.hprof。不指定则默认生成在启动目录下。
- 示例:
-XX:OnOutOfMemoryError="<cmd>":发生 OOM 时执行指定的脚本。- 示例:可用于发送告警邮件或自动重启服务(如
-XX:OnOutOfMemoryError="/opt/scripts/restart.sh")。
- 示例:可用于发送告警邮件或自动重启服务(如
四、 垃圾回收器选择(因地制宜)
根据业务场景(低延迟 vs 高吞吐)选择合适的 GC。
-XX:+UseG1GC:开启 G1 垃圾回收器(Java 9+ 的默认 GC)。适合大内存(多核),追求可控的停顿时间。- 配合使用:
-XX:MaxGCPauseMillis=200(设置目标最大 GC 停顿时间为 200ms)。
- 配合使用:
-XX:+UseZGC:开启 ZGC(Java 11 引入,Java 15+ 生产可用)。超低延迟 GC,停顿时间不到 10ms,适合对响应时间极度敏感的大型应用。-XX:+UseParallelGC:开启 Parallel Scavenge(并行)GC(Java 8 默认)。吞吐量优先,适合后台数据处理等不需要极低延迟的场景。- (已淘汰)
-XX:+UseConcMarkSweepGC:开启 CMS 垃圾回收器(Java 9 废弃,Java 14 移除)。
五、 GC 日志打印(监控与分析)
注意:Java 8 和 Java 9+ 的日志参数差异很大。
【Java 8 及以前】
-XX:+PrintGCDetails:打印详细的 GC 日志。-XX:+PrintGCDateStamps:在 GC 日志中添加时间戳。-Xloggc:<path>:将 GC 日志输出到指定文件(如-Xloggc:/logs/gc.log)。-XX:+UseGCLogFileRotation:开启 GC 日志轮转,防止日志把磁盘写满。
【Java 9 及以后 (Unified Logging)】
-Xlog:gc*:<path>:这是 Java 9 之后的标准写法,代替了上述 Java 8 的参数。- 示例:
-Xlog:gc*:/logs/gc.log:time,uptime:filecount=10,filesize=50M(记录包含时间的详细GC日志,按 50M 轮转,最多保留 10 个文件)。
- 示例:
六、 高级/其他实用参数
-XX:+DisableExplicitGC:禁用显式的System.gc()调用。很多框架(如 Netty/NIO)或烂代码可能会调用它引发 Full GC,开启此参数可屏蔽这些调用。-XX:+AlwaysPreTouch:在 JVM 启动时,强制分配并清零堆内存页。- 作用:会导致 JVM 启动变慢,但在运行时可以避免因操作系统内存缺页中断(Page Fault)带来的卡顿,对延迟敏感型应用(如高频交易、核心网关)很有用。
-server:强制以 Server 模式启动 JVM(通常64位机器默认就是此模式),启动慢但运行时性能(JIT 编译优化)更好。
💡 生产环境黄金组合示例(Java 8 常用模板):
bash
java -server \
-Xms4g -Xmx4g \
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m \
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/dumps/ \
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/logs/gc/gc.log \
-jar app.jar