【JVM】OOM详解+JVM参数+FullGC排查+CPU飙高+死锁+内存泄漏+命令大全

大家好,我是程序员二叉。


简介

本文整合面试 + 线上实战 全套 JVM 故障排查核心知识点:四大 OOM 类型成因、常用 JVM 参数、线上 OOM 标准排查流程、频繁 FullGC 定位方案、内存泄漏与内存溢出区别、CPU 飙高/线程死锁排查、JDK 工具命令、HeapDump 抓取与分析全流程,干货拉满。欢迎点赞关注收藏。


一、常见 4 种 OOM 类型及底层原因

1. 堆内存溢出(Java heap space)

报错: java.lang.OutOfMemoryError: Java heap space

核心原因:

  • 内存泄漏:无用对象持续被引用,GC 无法回收
  • 集合无限累加(List/Map 只增不减)
  • 一次性加载超大批量数据、未分页查询
  • -Xmx 最大堆内存设置过小

2. 元空间溢出(Metaspace)

报错: java.lang.OutOfMemoryError: Metaspace

核心原因:

  • 频繁动态生成 Class(CGLib、动态代理、SpringAOP)
  • 项目热部署、热加载频繁重复加载类
  • 大量反射、动态类加载场景
  • 配置了过小的 MaxMetaspaceSize

3. 栈溢出(StackOverflowError)

报错: java.lang.StackOverflowError

核心原因:

  • 方法无限递归调用
  • 递归深度过大
  • 线程栈 -Xss 设置过小

注意:栈溢出不属于 OOM,是线程栈帧溢出异常

4. 直接内存溢出(Direct buffer memory)

报错: java.lang.OutOfMemoryError: Direct buffer memory

核心原因:

  • NIO 使用 allocateDirect() 频繁分配直接内存
  • 直接内存未手动释放
  • 不受 -Xmx 限制,耗尽系统物理内存导致溢出

二、高频 JVM 参数详解(面试必背)

参数 作用说明
-Xms 初始堆内存大小,建议与 Xmx 一致
-Xmx 最大堆内存大小
-Xss 单个线程栈内存大小
-Xmn 新生代整体内存大小
-XX:MetaspaceSize 元空间初始值
-XX:MaxMetaspaceSize 元空间最大值,防止类加载OOM
-XX:MaxDirectMemorySize 限制NIO直接内存上限
-XX:+HeapDumpOnOutOfMemoryError OOM时自动导出堆快照
-XX:HeapDumpPath 指定dump文件存放路径
-XX:+PrintGCDetails 打印详细GC日志

三、线上 OOM 完整排查流程(标准实战流程)

  1. 提前配置JVM参数:OOM自动dump快照
  2. 服务崩溃后获取 .hprof 堆文件
  3. 使用 MAT / VisualVM / JProfiler 打开分析
  4. 查看大对象、实例数量、集合占用Top
  5. 追踪 GC Roots 引用链,定位无法回收对象
  6. 排查代码:静态集合累积、ThreadLocal未清理、IO未关闭、内存泄漏
  7. 代码优化:分页、手动释放、移除长引用
  8. 压测验证问题修复

四、频繁 Full GC 完整排查步骤

线上90%频繁FullGC = 内存泄漏

  1. jstat -gc PID 1000 实时观察GC变化
  2. 发现老年代持续上涨、频繁FullGC
  3. 查看GC日志,确认是空间不足/元空间满/手动GC
  4. dump堆快照分析存活大对象
  5. 定位长期累积无法回收的集合/对象
  6. 优化方案:
  • 修复内存泄漏
  • 批量查询分页处理
  • 减少大对象创建
  • 合理调优堆、元空间大小

五、内存泄漏 VS 内存溢出(高频面试)

1. 内存泄漏(Memory Leak)

  • 定义 :对象已无用,但存在有效引用,GC无法回收
  • 本质:对象占着内存不释放
  • 后果:内存缓慢上涨,最终触发OOM

典型泄漏场景:

  • static 静态集合缓存无限累加
  • ThreadLocal 使用不 remove
  • 连接、IO 流不关闭
  • 长生命周期持有短生命周期对象引用

2. 内存溢出(OOM)

  • 定义:JVM 内存资源耗尽,无法分配新对象
  • 本质:内存不够用

核心关系

内存泄漏是根源,内存溢出是最终结果


六、线上 CPU 飙高排查流程(生产万能套路)

  1. top 找到 CPU 100% 的 Java 进程 PID
  2. top -Hp PID 查看进程内最耗CPU线程TID
  3. printf "%x TID" 转为 16进制
  4. jstack PID | grep 16进制ID -A30
  5. 精准定位业务代码行

常见原因:

  • 代码死循环
  • 复杂逻辑运算、大数据遍历
  • 频繁GC、内存抖动
  • 锁自旋、线程竞争

七、线程死锁排查方法

  1. jps 获取Java进程号
  2. jstack PID 打印线程快照
  3. 检索关键字:deadlockwaiting to locklocked
  4. jstack 自动输出死锁线程 + 代码行数
  5. 调整锁顺序、加锁超时解决

八、JVM 五大排查命令作用总结

jps

查看所有Java进程PID,基础排查入口

jstack

线程问题神器:排查死锁、CPU飙高、线程阻塞、线程卡死

jmap

内存问题神器:查看堆使用、实例数量、导出dump文件

jstat

GC神器:实时监控新生代、老年代、GC次数、GC耗时

jhat

JDK内置dump分析工具(现已淘汰,用MAT)


九、堆 Dump 抓取 + 分析完整实战

1. 手动抓取dump

bash 复制代码
jmap -dump:format=b,file=heap.hprof PID

2. 线上自动抓取(推荐配置)

bash 复制代码
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/dump/

3. MAT 分析步骤

  1. 打开 hprof 文件
  2. Histogram:查看对象数量排行
  3. Dominator Tree:查看大对象占用排行
  4. 追踪 GC Root 定位泄漏源头
  5. 精准修复代码问题

十、全文核心总结(面试速背)

  1. 四类 OOM:堆溢出、元空间溢出、栈溢出、直接内存溢出
  2. 内存泄漏:对象无用不释放,是线上 OOM 最大元凶
  3. CPU 飙高排查链路:top → top -Hp → 16 进制 → jstack
  4. FullGC 频繁:绝大多数是内存泄漏导致
  5. OOM 排查核心:dump 快照 + MAT 分析 GC Roots 引用链
  6. 常用参数:Xms/Xmx 堆、Xss 栈、Metaspace 元空间
  7. 直接内存:不受堆限制,物理内存满照样 OOM
相关推荐
FBI HackerHarry浩几秒前
Pandas 库中用于分类变量独热编码(One-Hot Encoding)的函数 pd.get_dummies() 函数
开发语言·人工智能·python·pandas
名字还没想好☜15 分钟前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
黄敬峰36 分钟前
Harness 工程:用 LLM 当评委,自动生成、评测、择优一条龙
面试
ocean21031 小时前
八股刷题之:变体树
面试·面试题·面试真题·变体树·八股精·深度拓展·高效刷题
李可以量化1 小时前
Tornado 从了解到精通(一)下:异步与非阻塞 IO 核心原理
java·数据库·tornado
yurenpai(27届找实习中)1 小时前
从销售订单推送 MES 看懂微服务调用(二):DTO 转换与 OpenFeign 调用
java·微服务·架构·服务调用
运维行者_1 小时前
企业带宽监控工具实战:网络流量分析与异常排查的5个关键能力
运维·服务器·开发语言·网络·分布式·后端·php
Patrick在香港1 小时前
Python爬虫框架实战:优雅抓取香港政府公开API数据的通用方案
java·开发语言·爬虫·python·ai编程·数据可视化·可用性测试
hey_sml1 小时前
MySQL常用操作速记:从字符集到游标全解析
java·开发语言·mysql
广东程序猿小展1 小时前
《007初露锋芒》风灵月影13项修改器下载 007初露锋芒修改器使用方法
开发语言·javascript·ecmascript