面试知识库
进阶

JVM常用调优参数#

一句话答案#

核心参数:-Xms/-Xmx(堆大小)、-XX:+UseG1GC(收集器)、-XX:MaxGCPauseMillis(目标停顿)、-XX:+HeapDumpOnOOM。

核心要点

线程共享(所有线程共同访问):

  • 堆(Heap):对象实例存放在这里,多线程都可以访问 → 需要同步控制
  • 方法区(Metaspace):类信息、常量池、静态变量 → 需要同步控制

线程私有(每个线程独立拥有):

  • 虚拟机栈:每个线程有自己的栈,栈帧随方法调用入栈/出栈
  • 本地方法栈:同上,服务 native 方法
  • 程序计数器:记录线程自己的执行位置,线程切换时恢复

这是多线程内存可见性问题的根源:

  • 线程 A 修改了堆上的共享对象,线程 B 不一定立即可见(CPU 缓存与主存不一致)
  • Java 内存模型(JMM)通过 volatilesynchronizedhappens-before 规则来保证可见性
面试回答(2分钟版)

JVM 调优参数我按内存、GC、诊断三个维度来说。内存方面,-Xms 和 -Xmx 设置堆的初始和最大值,建议设成一样避免运行时堆动态伸缩带来的性能开销;-XX:MetaspaceSize 和 MaxMetaspaceSize 控制元空间大小,动态代理或大量类加载的应用需要适当调大。GC 方面,-XX:+UseG1GC 选择 G1 收集器,配合 -XX:MaxGCPauseMillis 设置目标停顿时间,G1 会自动调整 Region 回收策略来尽量满足目标。诊断方面,-XX:+HeapDumpOnOutOfMemoryError 是必配参数,OOM 时自动导出堆快照保留现场;-Xloggc 开启 GC 日志用于事后分析。理解这些参数背后的原理很重要:堆是线程共享区域存放对象实例,栈和程序计数器是线程私有的天然安全,多线程可见性问题的根源就在于线程工作内存和主内存的不一致,需要 volatile 和 synchronized 来保证。实际调优要结合业务场景和压测数据,不能照搬网上配置。

追问与易错

追问方向:

  • “-Xms 和 -Xmx 为什么建议设成一样?”→ 避免 JVM 运行时动态伸缩堆大小带来的性能开销和 GC 停顿,预分配固定内存减少内存申请和释放的系统调用
  • “怎么选择 GC 收集器?”→ 吞吐优先选 Parallel GC,低延迟选 G1(堆 > 4GB)或 ZGC(超大堆),JDK8 默认 Parallel,JDK9+ 默认 G1;小堆 + 单核可用 Serial
  • “你在生产环境设过哪些 JVM 参数?”→ 经验题,常见组合:-Xms/-Xmx 设相同值、-XX:+UseG1GC、-XX:MaxGCPauseMillis=200、-XX:+HeapDumpOnOutOfMemoryError、-Xloggc 开启 GC 日志、-XX:MetaspaceSize 调大防频繁 Full GC

易错点:

  • ❌ 照搬网上参数不结合实际场景
  • ❌ 忘记设 HeapDumpOnOOM