关于jvm的参数以及OOM

JVM 参数优化内存占用与 OOM 监控发现

一、JVM 参数优化内存占用的几个方面

1. 堆内存(Heap)优化

参数 说明 优化建议
-Xms 初始堆大小 -Xmx 设置一致,避免堆动态扩缩容带来的开销
-Xmx 最大堆大小 根据实际需求设置,通常为物理内存的 50%~70%
-XX:NewRatio 老年代/新生代比例 默认 2,即老年代:新生代=2:1,根据对象存活特点调整
-XX:SurvivorRatio Eden/Survivor 比例 默认 8,增大可使 Eden 更大,减少 Minor GC 频率

2. 元空间(Metaspace)优化

参数 说明 优化建议
-XX:MetaspaceSize 初始元空间大小 设置合理初始值,避免元空间扩容触发 Full GC
-XX:MaxMetaspaceSize 最大元空间大小 必须设置上限,防止元空间无限增长导致 OOM

3. 直接内存(Direct Memory)优化

参数 说明 优化建议
-XX:MaxDirectMemorySize 最大直接内存 NIO 使用直接内存,需显式限制,默认与 -Xmx 一致

4. 线程栈优化

参数 说明 优化建议
-Xss 每个线程的栈大小 默认 1MB,线程数多时可适当降低(如 256k~512k)

5. GC 算法选择

参数 说明 适用场景
-XX:+UseG1GC G1 收集器 大堆内存(>4GB),追求低停顿
-XX:+UseZGC ZGC 收集器 超大堆内存(>16GB),极低停顿
-XX:+UseParallelGC 并行收集器 吞吐量优先,后台计算型应用
-XX:+UseConcMarkSweepGC CMS 收集器 JDK8 常用,已逐步废弃

6. GC 优化相关参数

-XX:+DisableExplicitGC          # 禁止 System.gc() 触发 Full GC
-XX:+ExplicitGCInvokesConcurrent # System.gc() 走并发 GC 而非 Full GC
-XX:InitiatingHeapOccupancyPercent=45  # G1 触发并发标记的堆占用阈值
-XX:G1HeapRegionSize=8m         # G1 Region 大小
-XX:MaxGCPauseMillis=200        # G1 目标最大停顿时间

二、如何监控并发现 OOM

1. 开启 OOM 时的堆转储(最重要)

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump/${date}.hprof
-XX:OnOutOfMemoryError="script.sh"  # OOM 时执行脚本(如告警、重启)

OOM 发生后自动生成 .hprof 文件,可用 MAT(Memory Analyzer Tool)或 JProfiler 分析。

2. GC 日志监控

# JDK8
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log

# JDK11+
-Xlog:gc*:file=/path/to/gc.log:time,uptime,level,tags

关注指标:

  • Full GC 频率和耗时:频繁 Full GC 是 OOM 前兆
  • 老年代使用率:持续上升不下降,说明内存泄漏
  • GC 后堆回收率:回收比例越来越低,表明对象无法回收

3. JMX 监控(运行时)

// 通过 JMX 获取内存指标
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryMXBean.getHeapMemoryUsage();
long used = heapUsage.getUsed();       // 已使用
long max = heapUsage.getMax();         // 最大可用
double usageRatio = (double) used / max; // 使用率

4. 常用监控命令行工具

工具 用途 示例
jstat 监控 GC 统计 jstat -gcutil <pid> 1000
jmap 查看堆内存 jmap -heap <pid>
jcmd 诊断命令 jcmd <pid> GC.heap_info
jconsole 可视化监控 JMX 连接
Arthas 在线诊断 dashboard / heapdump

5. 告警策略建议

告警规则(基于 GC 日志或 JMX 指标):
├── 堆内存使用率 > 85% 持续 3 分钟     → P1 告警
├── Full GC 频率 > 1次/分钟            → P2 告警
├── Full GC 后老年代回收率 < 20%       → P2 告警(疑似内存泄漏)
├── Metaspace 使用率 > 90%            → P2 告警
└── OOM Error 触发                     → P0 告警(自动重启)

6. OOM 排查思路

发现 OOM
  │
  ├── 1. 确认 OOM 类型
  │     ├── Java heap space      → 堆内存不足
  │     ├── Metaspace            → 类加载过多/未卸载
  │     ├── Direct buffer memory → 直接内存泄漏
  │     ├── GC overhead limit    → GC 回收效率过低
  │     └── unable to create new native thread → 线程数过多
  │
  ├── 2. 分析 HeapDump(MAT)
  │     ├── Dominator Tree → 查看最大对象
  │     ├── Leak Suspects  → 自动检测泄漏点
  │     └── GC Roots 引用链 → 定位无法回收的原因
  │
  └── 3. 结合代码修复
        ├── 释放未关闭的资源(连接、流)
        ├── 缓存设置上限和过期策略
        ├── 修复 ThreadLocal 泄漏
        └── 优化大对象创建/复用

三、推荐的生产环境 JVM 参数模板

以 JDK8 + G1 为例:

-Xms4g -Xmx4g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
-XX:MaxDirectMemorySize=512m
-Xss512k
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/home/admin/logs/heapdump.hprof
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/home/admin/logs/gc.log
-XX:+DisableExplicitGC
-Djava.security.egd=file:/dev/./urandom

核心原则-Xms-Xmx 设为相同值避免堆抖动;Metaspace 和 DirectMemory 必须设上限;务必开启 HeapDumpOnOutOfMemoryError,这是事后排查 OOM 最关键的手段。

posted @ 2026-05-13 14:19  webzd  阅读(1)  评论(0)    收藏  举报