一、OOM(OutOfMemoryError)问题处理
1. 什么是 OOM?
OOM 表示 Java 程序内存不足,无法继续分配空间,常见异常包括:
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Metaspace
java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: Unable to create new native thread
常见原因:
内存泄漏
高并发占满内存
JVM 配置太小
无限创建线程
2. 如何判断是否是 OOM?
2.1 查看日志
搜索关键词:“OutOfMemoryError”。
2.2 查看系统层信息
top -Hp <pid>
ps -ef | grep java
dmesg | grep -i oom
3. OOM 定位方法
3.1 导出 Heap Dump
自动 dump:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/dump/
手动 dump:
jmap -dump:live,format=b,file=heap.hprof <pid>
3.2 使用工具分析 dump
工具 用途
MAT 分析内存泄漏、对象占比
VisualVM 查看内存、线程、GC
JProfiler 商业工具,更强大
分析重点:
Leak Suspects
Dominator Tree
Histogram(对象数量)
4. OOM 的解决方式
4.1 调整 JVM 参数
-Xms4g -Xmx4g
-XX:MaxMetaspaceSize=512m
4.2 解决代码问题
常见泄漏点:
静态集合不断增长
未关闭连接(JDBC、Redis)
缓存无过期时间
无限 new 线程
4.3 限流、降级、熔断
适用于流量突增导致的 OOM。
4.4 调整线程池
避免过多线程导致:
java.lang.OutOfMemoryError: unable to create new native thread
二、线程死锁问题处理
1. 什么是线程死锁?
两个或多个线程互相等待对方持有的锁,最终所有线程无法继续执行。
2. 死锁特征
CPU 占用低
程序卡死无响应
jstack 中出现 deadlock
线程状态为 BLOCKED
3. 死锁排查方式
3.1 jstack 排查
jstack <pid> > thread.log
搜索:
deadlock
BLOCKED
waiting to lock
3.2 top 查看线程
top -Hp <pid>
将 tid 转 16 进制:
printf "%x\n" <tid>
然后在 jstack 中查找对应线程。
3.3 可视化工具
VisualVM → Threads 面板查看 BLOCKED 状态
4. 死锁解决方案
4.1 统一加锁顺序
避免:
线程1:A → B
线程2:B → A
统一改为:
永远先 A,再 B
4.2 使用 tryLock 防止死锁
if (lockA.tryLock(1, TimeUnit.SECONDS)) {
try {
if (lockB.tryLock(1, TimeUnit.SECONDS)) {
// do something
}
} finally {
lockA.unlock();
lockB.unlock();
}
}
4.3 减少锁的粒度
缩小 synchronized 范围。
4.4 使用更安全的并发类
传统方式 替代
synchronized List CopyOnWriteArrayList
HashMap + 锁 ConcurrentHashMap
synchronized ReentrantLock / StampedLock
三、常用命令总结(收藏)
内存排查
jmap -dump:format=b,file=heap.hprof <pid>
jmap -histo <pid>
jstat -gc <pid> 1000
jps
dmesg | grep -i oom
线程排查
jstack <pid> > thread.log
top -Hp <pid>
ps -mp <pid> -o THREAD,tid,time
printf "%x\n" <tid>
Docker 排查
docker logs <container>
docker stats
docker exec -it <container> bash
四、总结
OOM:通过 Heap Dump 找根因,优化代码 + 调整 JVM。
死锁:通过 jstack 识别锁依赖链,优化加锁顺序或使用 tryLock。
必须结合日志、监控、内存分析、线程分析综合排查
评论