# JVM性能常见问题及解决方案
一、垃圾收集(GC)相关问题
1. GC停顿时间过长
- 原因:堆内存设置过小、GC算法选择不当
- 解决方案:
- 切换至低延迟GC算法:
-XX:+UseG1GC
(Java 7+)或-XX:+UseZGC
(Java 11+) - 调整堆大小:
-Xmx4g -Xms4g
(设置初始堆=最大堆,避免扩容) - 优化代空间比例:
-XX:NewRatio=2
(老年代:新生代=2:1)
- 切换至低延迟GC算法:
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
- 核心线程数=CPU核心数×1~2,队列使用
2. 锁竞争严重
- 原因:多线程竞争同一锁资源
- 解决方案:
- 减少锁粒度(如
ConcurrentHashMap
分段锁) - 启用偏向锁:
-XX:+UseBiasedLocking
(默认开启) - 避免伪共享:
@Contended
注解(Java 8+)
- 减少锁粒度(如
五、数据库交互问题
1. 连接池耗尽
- 原因:maxActive设置过小、连接未归还
- 解决方案:
- 调整连接池参数:
maxActive=20
,minIdle=5
- 使用预处理语句池:
useServerPrepStmts=true
(MySQL驱动)
- 调整连接池参数:
2. JPA查询N+1问题
- 原因:关联查询未使用fetch join
- 解决方案:
- 优化JPQL:
SELECT e FROM Entity e JOIN FETCH e.relation
- 启用二级缓存:
@Cacheable(true)
- 优化JPQL: