StayInLove头像
关注

JVM问题排查

项目是 JDK 8,下面按这个环境给你一套实操流程。

一、OOM 排查

1. 事先埋点(最重要)

启动参数加上:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/dump/

OOM 时自动生成 java_pidxxx.hprof 文件,没有它就只能靠现场命令抓。

2. 运行中现场抓取

jps -l                          # 找到进程号
jmap -histo:live <pid> | head -30   # 快速看哪些类实例最多、占内存最大(会触发一次Full GC,低峰期执行)
jmap -dump:live,format=b,file=heap.hprof <pid>   # 导出完整堆快照(STW几秒,生产慎用)

3. 用 MAT 分析 dump

工具:Eclipse MAT(Memory Analyzer Tool),打开 .hprof 文件:

  • Leak Suspects 报告:自动给出泄漏疑点,直接告诉你哪个类占了百分之多少的堆
  • Dominator Tree:按内存占用排序列出对象,找到最大的那个
  • 右键对象 → Path to GC Roots (exclude weak/soft references):看到完整的引用链,比如 XXController.cache → HashMap → 100万个User对象,引用链的持有者就是泄漏代码的位置

4. 常见 OOM 类型对症

报错信息方向
Java heap space堆内存泄漏/不够,走上面 MAT 流程
Metaspace反射/CGLIB 动态生成类没释放,看 Class.forName、动态代理
unable to create new native thread线程数爆了,jstack <pid> 看线程数和线程名
Direct buffer memoryNIO 堆外内存,-XX:MaxDirectMemorySize + Netty 相关

5. 常见根因(代码层面)

  • 静态 Map/List 只 put 不 remove(本地缓存无上限、无过期)
  • ThreadLocal 没 remove(线程池场景必漏)
  • 监听器/回调注册后没注销
  • 一次性查全表的大 SQL 结果集

二、频繁 Full GC 排查

1. 先看 GC 行为定性

jstat -gcutil <pid> 1000   # 每秒打印一次

看两列关键信息,连续观察 1 分钟:

  • O(老年代)持续涨,Full GC 后降不下来 → 内存泄漏,回到 OOM 排查流程
  • FGC 数字持续增加但每次 O 能降下去 → 老年代进对象太快:大对象、Young 区太小、Survivor 放不下提前晋升
  • FGC 次数和 元空间/M 区 相关 → 类加载问题

2. 打开 GC 日志(JDK 8 语法)

-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/data/gc.log

把 gc.log 丢到 gceasy.io(网页版,免费)分析,会告诉你:晋升失败原因、大对象分配、GC 停顿分布。

3. 定位是谁在分配内存

  • Arthas(阿里开源,生产可用,推荐):
    curl -O https://arthas.aliyun.com/arthas-boot.jar
    java -jar arthas-boot.jar   # 选进程
    dashboard                   # 总览,直接看堆各区和FGC次数
    heapdump /tmp/heap.hprof    # 也能导出dump给MAT
    profiler start / profiler stop   # 生成内存分配火焰图,直接看到哪个方法在疯狂分配对象
    
  • JProfiler / async-profiler:CPU/内存火焰图,定位到具体分配热点方法

4. 常见根因

  • 系统缓存放本地大对象(一次加载数十万条进内存)
  • 大对象(超过 -XX:PretenureSizeThreshold 或 Young 区一半)直接进老年代
  • 显式调用 System.gc()(排查依赖库,可加 -XX:+DisableExplicitGC
  • Young 区太小导致对象过早晋升,Full GC 频繁但不是泄漏(调大 -Xmn 或改用 G1)

三、快速决策树

频繁FGC
 ├─ jstat 看 O 区 Full GC 后是否回落
 │   ├─ 降不下来 → 泄漏 → jmap -histo → MAT → 引用链定位类
 │   └─ 降得下来 → 分配太快 → GC日志/gceasy → Arthas profiler 火焰图找分配热点
 └─ 伴随 OOM → 先确保 HeapDumpOnOutOfMemoryError 开着,dump 后 MAT Leak Suspects

建议现在就检查一下线上启动脚本有没有加 HeapDumpOnOutOfMemoryError 和 GC 日志参数——这两个是事后排查的生命线,OOM 时没有 dump 就只能靠猜了。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/qq_28919337/article/details/164851119

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--