JVM性能常见问题及解决方案

Scroll Down
# JVM性能常见问题及解决方案

一、垃圾收集(GC)相关问题

1. GC停顿时间过长

  • 原因:堆内存设置过小、GC算法选择不当
  • 解决方案
    • 切换至低延迟GC算法:-XX:+UseG1GC(Java 7+)或-XX:+UseZGC(Java 11+)
    • 调整堆大小:-Xmx4g -Xms4g(设置初始堆=最大堆,避免扩容)
    • 优化代空间比例:-XX:NewRatio=2(老年代:新生代=2:1)

2. 内存泄漏导致OOM

  • 原因:静态集合未清理、资源未关闭、长生命周期对象持有短生命周期引用
  • 解决方案
    • 使用弱引用/软引用管理缓存:WeakReference<CacheObject>
    • 工具排查:jmap -dump:format=b,file=heap.hprof <pid> + MAT分析
    • 优先使用try-with-resources关闭资源

二、JIT编译优化问题

1. 热点方法未被优化

  • 原因:编译阈值过高、代码缓存溢出
  • 解决方案
    • 降低编译阈值:-XX:CompileThreshold=5000
    • 扩大代码缓存:-XX:ReservedCodeCacheSize=256m
    • 启用分层编译:-XX:+TieredCompilation(默认开启)

2. 内联失败

  • 原因:方法体过大、调用链复杂
  • 解决方案
    • 简化热点方法(建议≤30行)
    • 调整内联参数:-XX:MaxInlineSize=200

三、内存管理问题

1. 新生代GC频繁

  • 原因:新生代空间过小、对象快速进入老年代
  • 解决方案
    • 调整新生代大小:-Xmn1g-XX:SurvivorRatio=8
    • 启用逃逸分析:-XX:+DoEscapeAnalysis(默认开启)

2. 原生内存泄漏

  • 原因:DirectByteBuffer未释放、JNI内存未回收
  • 解决方案
    • 监控原生内存:-XX:NativeMemoryTracking=summary + jcmd <pid> VM.native_memory
    • 限制直接缓冲区大小:-XX:MaxDirectMemorySize=128m

四、线程与同步问题

1. 线程池配置不合理

  • 原因:核心线程数过多/过少、队列容量不足
  • 解决方案
    • 核心线程数=CPU核心数×1~2,队列使用LinkedBlockingQueue
    • 高并发计算场景使用ForkJoinPool

2. 锁竞争严重

  • 原因:多线程竞争同一锁资源
  • 解决方案
    • 减少锁粒度(如ConcurrentHashMap分段锁)
    • 启用偏向锁:-XX:+UseBiasedLocking(默认开启)
    • 避免伪共享:@Contended注解(Java 8+)

五、数据库交互问题

1. 连接池耗尽

  • 原因:maxActive设置过小、连接未归还
  • 解决方案
    • 调整连接池参数:maxActive=20minIdle=5
    • 使用预处理语句池:useServerPrepStmts=true(MySQL驱动)

2. JPA查询N+1问题

  • 原因:关联查询未使用fetch join
  • 解决方案
    • 优化JPQL:SELECT e FROM Entity e JOIN FETCH e.relation
    • 启用二级缓存:@Cacheable(true)