一、明确问题现象

  1. 常见问题类型
    • 内存溢出(OutOfMemoryError
    • CPU占用率飙升(100%)
    • 线程阻塞/死锁(应用无响应)
    • GC频繁(应用卡顿)
    • 类加载异常(ClassNotFoundException/NoClassDefFoundError

二、基础信息收集

1. 查看JVM参数

1
2
jps -lvm  # 列出所有Java进程及其启动参数
jinfo <pid> # 查看指定进程的详细配置

关键参数:堆大小(-Xms, -Xmx)、GC算法(-XX:+UseG1GC)、OOM行为(-XX:+HeapDumpOnOutOfMemoryError

2. 实时监控

1
jstat -gcutil <pid> 1000  # 每秒打印一次GC情况

输出关键指标

  • YGC/YGCT:Young GC次数/耗时
  • FGC/FGCT:Full GC次数/耗时
  • O:老年代使用率
  • M:元空间使用率

三、深度排查工具

1. 内存问题排查

  • 堆内存分析

    1
    2
    jmap -dump:format=b,file=heap.hprof <pid>  # 生成堆转储文件
    jmap -histo:live <pid> | head -20 # 查看存活对象统计(生产慎用!)

    分析工具

    • Eclipse MAT:分析内存泄漏(Dominator Tree查找大对象)
    • VisualVM:实时堆内存监控
  • Native内存泄漏

    1
    pmap -x <pid> | sort -n -k3  # 查看进程物理内存分布

2. CPU占用高排查

  1. 定位高CPU线程
    1
    2
    top -H -p <pid>   # 查看进程内线程CPU占用
    printf "%x\n" <tid> # 将线程ID转为16进制
  2. 抓取线程栈
    1
    jstack <pid> > thread_dump.txt
  3. 分析
    • 查找对应16进制线程ID的栈信息
    • 关注RUNNABLE状态的线程(尤其是长时间运行的代码)

3. 线程阻塞/死锁

1
2
jstack <pid> | grep -A 10 "BLOCKED"  # 查找阻塞线程
jstack <pid> | grep -i deadlock # 检测死锁

典型场景:锁竞争、I/O阻塞、数据库连接池耗尽

4. GC问题排查

  • 开启GC日志(启动参数):
    1
    -Xloggc:/path/to/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps
  • 分析工具
    • GCeasy:在线分析GC日志
    • G1GC推荐添加:-XX:+PrintTenuringDistribution(查看晋升详情)

常见GC问题

  • Full GC频繁:老年代空间不足 / 元空间溢出
  • Young GC时间长:新生代过大 / 对象晋升过快

四、高级诊断工具

  1. Arthas(阿里开源) - 动态诊断神器

    1
    2
    3
    4
    5
    # 追踪方法调用耗时
    trace com.example.Service *methodName

    # 监控方法执行统计
    monitor -c 5 com.example.Service *methodName
  2. Async-Profiler - 低开销性能分析

    1
    ./profiler.sh -d 60 -f flamegraph.html <pid>  # 生成CPU火焰图
  3. JDK Mission Control - 官方性能分析套件

    • 安全点分析、JFR(Java Flight Recorder)录制

五、常见问题速查表

问题现象 优先检查项
OOM 堆转储分析 + MAT Dominator Tree
CPU 100% jstack定位线程 + 火焰图
应用卡顿 GC日志分析(是否GC导致STW)
线程数暴涨 jstack统计线程状态 + 线程池配置
请求延迟高 链路追踪 + 数据库慢查询

六、预防性建议

  1. 监控先行
    • Prometheus + Grafana监控:JVM内存、GC次数、线程池状态
    • 添加APM工具(SkyWalking, Pinpoint)
  2. 参数调优
    • 根据压测结果设置堆大小(避免默认值)
    • G1GC推荐:-XX:MaxGCPauseMillis=200
  3. 代码规范
    • 避免大对象(如byte[100MB]
    • 及时关闭资源(数据库连接、文件流)

关键原则:通过堆转储和线程栈能解决80%问题,复杂场景结合Profiler工具深入分析。生产环境避免直接使用jmap -histo:live(可能触发Full GC)!