基于本文回答
0
评论

请列举你熟悉的常用 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
右滑查看面试常问