《Java 100 天进阶之路》第65篇:OOM与内存泄漏排查(2026版)
第65篇OOM与内存泄漏排查2026精版系列导航《Java 100 天进阶之路》完整目录 |⬅️ 上一篇第64篇类加载器与热部署 |➡️ 下一篇第66篇JIT编译与性能优化️ 本文阅读地图3 分钟速览第61~64篇搞定了JVM内存、GC、类加载器但线上OOM来了怎么办本篇直击OOM与内存泄漏排查实战。OOM是Java生产环境的“头号杀手”但排查有章可循模块核心问题一句话回答OOM类型OOM有哪几种Heap Space最常见、Metaspace、Direct Buffer、GC Overhead、Unable to create native thread内存泄漏 vs 内存溢出有什么区别泄漏是“慢慢漏”溢出是“瞬间炸”——泄漏是溢出的最常见原因排查流程怎么查看日志 → jstat监控 → jmap dump → MAT分析 → 修复验证五步闭环核心工具用什么工具jstat实时监控、jmap堆快照、MAT深度分析、Arthas生产在线诊断常见泄漏场景哪里最容易漏静态集合、未关闭资源、ThreadLocal、内部类持有外部引用、类加载器泄漏面试最爱问高频考点有哪些见文末 小节核心原则遇到OOM先看日志确认类型再针对性排查不要一上来就dump堆。一、核心知识点1. 内存泄漏 vs 内存溢出术语英文含义类比内存泄漏Memory Leak已分配的内存无法被GC回收可用内存逐渐减少水龙头没关紧一滴一滴漏迟早水漫金山内存溢出OutOfMemoryError (OOM)内存耗尽JVM无法继续分配对象水缸满了继续加水就会溢出核心关系内存泄漏是内存溢出的最常见原因。排查OOM本质上是排查内存泄漏。2. OOM的五种核心类型OOM类型错误信息根本原因排查方向堆内存溢出Java heap space堆内存不足以容纳对象最常见检查大对象、内存泄漏、堆大小元空间溢出Metaspace类元数据占满元空间检查动态类加载、类加载器泄漏直接内存溢出Direct buffer memoryNIO直接内存堆外耗尽检查Netty/DirectByteBuffer使用GC OverheadGC overhead limit exceededGC回收98%内存却腾不出空间基本等于内存泄漏按泄漏排查线程溢出unable to create new native thread线程数超过系统限制检查线程池配置、线程泄漏快速判断OOM日志是第一手线索先看错误信息中的关键词再决定后续排查方向。二、通俗讲解1分钟开心学把JVM内存想象成一个水缸系统堆内存水缸主体装水对象。漏水内存泄漏时水慢慢减少加水太快大对象暴增时水溢出Heap Space OOM。元空间水缸旁边的“目录架”存书的分类信息类元数据。书太多动态生成类太多时目录架被塞满Metaspace OOM。直接内存水缸外的“管道”水流NIO数据从这里快速通过。管道太窄或堵住DirectBuffer过多水流不畅Direct buffer memory OOM。排查就像修水管看水表看日志确认是哪个区域出了问题。监控水位jstat看水位变化趋势。抽水检查jmap dump把水抽出来看里面有什么。实验室分析MAT找出到底是哪个阀门在漏水。修好阀门修复代码把漏水的根源堵住。三、五步排查流程2026实战版第一步看日志——确认OOM类型# 堆内存溢出 java.lang.OutOfMemoryError: Java heap space # 元空间溢出 java.lang.OutOfMemoryError: Metaspace # 直接内存溢出 java.lang.OutOfMemoryError: Direct buffer memory # GC Overhead基本等于内存泄漏 java.lang.OutOfMemoryError: GC overhead limit exceeded⚠️重要OOM时日志中会明确告诉你是哪种类型先看类型再行动不要盲目操作。第二步jstat——实时监控GC状态# 查看GC状态每秒输出一次共10次jstat-gcutilpid100010# 输出示例S0 S1 E O M CCS YGC YGCT FGC FGCT GCT0.000.0045.2398.7692.3489.12123412.34556745.67858.023快速判断标准O老年代使用率长期 95% →内存泄漏FGCFull GC次数每小时涨几百次 →内存泄漏EEden区频繁满 → 对象分配过快YGC次数多但YGCT很低 → 新生代偏小第三步jmap——生成堆快照# 方式1手动dump生产环境谨慎操作建议低峰期jmap-dump:formatb,file/tmp/heap.hprofpid# 方式2OOM时自动dump推荐生产开启-XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath/tmp/heap.hprof⚠️重要警告jmap dump时JVM会STWStop-The-World生产环境必须在低峰期操作。推荐配置自动dumpOOM发生时自动生成无需人工介入。OOM自动dump完整配置-XX:HeapDumpOnOutOfMemoryError-XX:HeapDumpPath/var/log/heap.hprof-XX:PrintGCDetails-Xloggc:/var/log/gc.log-XX:UseGCLogFileRotation-XX:NumberOfGCLogFiles10-XX:GCLogFileSize100M第四步MAT——深度分析堆快照1. 导入堆快照将.hprof文件拖入MAT生成“Leak Suspects Report”泄漏检测报告。2. 三大核心视图视图作用使用场景Histogram直方图按类统计实例数和内存占用找出占用内存最多的类Dominator Tree支配树找出保留最多内存的对象根节点定位大对象持有者Path to GC Roots显示对象为何无法被回收的引用链追踪泄漏根源3. 泄漏排查标准流程① 打开Leak Suspects Report红色爆炸图标指向泄漏源头 ② 定位可疑类右键 → Path to GC Roots ③ 选择 exclude all phantom/weak/soft etc. references ④ 找到强引用链定位泄漏代码4. 堆快照损坏的应急处理2026新增高频场景线上dump的hprof文件可能因OOM瞬间进程强制退出、磁盘空间不足等原因被截断。MAT报错HPROF parser encountered a violation时# 临时方案放宽MAT严格模式# Preferences → HPROF Parser → Strictness → 改为 Warning 或 Permissive# 或启动MAT时加参数-DhprofStrictnessWarningtrue⚠️ 强行解析后部分数据会缺失仅应急用正式排查建议重新生成完整堆文件。第五步修复与验证根据MAT分析结果修复代码再次用jstat监控验证泄漏是否已修复。四、常见内存泄漏场景与代码示例场景1静态集合类持有对象// ❌ 错误静态List永不释放publicclassCacheManager{privatestaticListObjectcachenewArrayList();publicvoidadd(Objectobj){cache.add(obj);}// 只增不减}// ✅ 正确使用WeakHashMap或设置缓存上限privatestaticMapString,ObjectcachenewWeakHashMap();// 或使用Caffeine/Guava Cache设置过期时间场景2未关闭的资源// ❌ 错误未关闭连接publicvoidreadFile(Stringpath){FileInputStreamfisnewFileInputStream(path);// 使用fis忘记close}// ✅ 正确try-with-resources自动关闭try(FileInputStreamfisnewFileInputStream(path)){// 使用fis}// 自动关闭场景3ThreadLocal未清理// ❌ 错误线程池中ThreadLocal未removeThreadLocalStringcontextnewThreadLocal();context.set(userId);// 任务结束未调用remove()// 线程池复用 → userId残留且内存泄漏// ✅ 正确try-finally保证removetry{context.set(userId);// 业务逻辑}finally{context.remove();// 必须}特别注意多次热部署后Metaspace持续增长很可能是类加载器泄漏——旧的WebappClassLoader未释放其加载的所有类都无法回收。场景4内部类持有外部类引用// ❌ 错误非静态内部类隐式持有外部类classOuter{classInner{/* 隐式持有Outer.this */}voidmethod(){InnerinnernewInner();// 外部类无法被GC}}// ✅ 正确使用静态内部类staticclassInner{/* 不持有外部引用 */}场景5Druid连接池SQL统计泄漏#Druid配置不当导致SQL统计无限累积 # 错误未限制SQL统计缓存大小# ✅ 正确限制缓存大小关闭不必要的统计spring.datasource.druid:filter.stat.merge-sql:truefilter.stat.slow-sql-millis:5000# 限制连接池监控缓存数量web-stat-filter.session-stat-enable:false五、核心工具链速查工具类型核心命令适用场景jstatJDK内置jstat -gcutil pid 1000实时监控GC判断泄漏趋势jmapJDK内置jmap -dump:formatb,fileheap.hprof pid生成堆快照jhatJDK内置jhat heap.hprof离线分析堆快照Web界面jstackJDK内置jstack pid线程快照排查死锁/阻塞MAT独立工具导入.hprof文件深度泄漏分析、引用链追踪VisualVMJDK内置jvisualvm实时监控、采样分析Arthas阿里开源heapdump、heap、jad生产在线诊断、无需重启工具选型建议开发/测试用VisualVM生产实时监控用jstat深度分析用MAT生产紧急排查用Arthas。六、避坑要点错误/误区后果正确做法遇到OOM第一反应是jmap dump生产环境STW可能引发雪崩先看日志确认OOM类型再行动OOM后暴力扩容加-Xmx掩盖内存泄漏OOM卷土重来先排查泄漏再考虑扩容生产未开启HeapDumpOnOOMOOM后无法分析根因生产环境必须开启MAT解析hprof文件报错就放弃错过排查机会放宽严格模式应急解析jmap dump在生产高峰期执行STW导致接口超时低峰期操作或用自动dumpThreadLocal用完不remove线程池场景内存泄漏try-finally保证remove只看堆内存忽略元空间/直接内存遗漏其他OOM类型根据日志类型针对性排查七、面试高频考点Q1内存泄漏和内存溢出的区别内存泄漏是对象无法被GC回收可用内存逐渐减少内存溢出是内存耗尽JVM无法继续分配对象。内存泄漏是内存溢出的最常见原因。Q2OOM有哪几种常见类型如何排查五种核心类型①Java heap space堆内存溢出→ jstat看GC jmap dump MAT分析②Metaspace元空间溢出→ 检查类加载器泄漏③Direct buffer memory直接内存溢出→ 检查NIO/Netty使用④GC overhead limit exceeded→ 基本等于内存泄漏⑤unable to create new native thread→ 检查线程池配置。Q3生产环境OOM排查的标准流程是什么五步闭环①看日志确认OOM类型②jstat监控GC状态③jmap dump或自动dump生成堆快照④MAT深度分析⑤修复代码并验证。Q4常用的OOM排查工具有哪些①jstat实时GC监控②jmap生成堆快照③MAT深度泄漏分析④VisualVM可视化监控⑤Arthas生产在线诊断。Q5如何防止OOM在生产环境发生① 生产环境强制开启-XX:HeapDumpOnOutOfMemoryError② 开启GC日志③ 配置合理的-Xmx和-Xms④ 代码层面避免静态集合无限增长、资源及时关闭、ThreadLocal及时remove⑤ 定期review和压测。 面试官追问陷阱加分题追问1“MAT分析hprof文件时Path to GC Roots为什么要排除弱引用和软引用” GC Roots路径中弱引用WeakReference和软引用SoftReference在GC时会被回收不会造成内存泄漏。只有强引用链才是泄漏的根本原因。排除弱/软/虚引用后留下的就是真正的泄漏根源。追问2“Metaspace OOM最常见的场景是什么怎么排查” 最常见的是类加载器泄漏——热部署时旧的WebappClassLoader未释放其加载的所有类都无法被GC回收。排查方法用jstat -gc pid看Metaspace使用率持续增长用MAT分析hprof找ClassLoader相关的大对象检查是否有自定义类加载器未正确释放。追问3“OOM自动生成的hprof文件被截断了MAT打不开怎么办” 三种应急方案① 放宽MAT严格模式Preferences → HPROF Parser → Strictness → Warning/Permissive② 添加启动参数-DhprofStrictnessWarningtrue③ 使用其他工具如VisualVM尝试打开。强行解析后部分数据会缺失正式排查建议重新生成完整堆文件。八、练习题分析题某服务jstat显示老年代使用率持续98%以上FGC每小时数百次。这是什么问题下一步应该做什么场景题一个Spring Boot应用频繁热部署后出现OutOfMemoryError: Metaspace分析可能原因和解决方案。代码题下面的代码有什么问题如何修复publicclassUserContext{privatestaticThreadLocalStringuserIdnewThreadLocal();publicstaticvoidsetUserId(Stringid){userId.set(id);}// 使用userId但从未remove}实战题配置生产环境JVM参数要求OOM时自动生成堆快照到/data/dump/heap.hprof并开启GC日志轮转。 你的学习进度当前第65篇 / 共108篇 ·进阶篇JVM调优与故障排查第61~70篇✅ 已完成基础篇44篇 第45~65篇 正在学第65篇⏳ 待学习第66~108篇 完整目录 学习指南 | 订阅本专栏不错过每一篇 下一篇文章预告下一篇《第66篇JIT编译与性能优化》内容简介JIT即时编译器原理、热点代码检测、逃逸分析、栈上分配、锁消除、内联优化以及JVM编译参数调优。JVM调优专题持续深入拿下JIT编译器《Java 100 天进阶之路 | 从入门到上岗就业》每天一篇建议收藏 关注一起100天拿offer 点击关注我更新后第一时间收到推送

相关新闻

基于西门子PLC的自动装瓶机控制系统设计与实现

基于西门子PLC的自动装瓶机控制系统设计与实现

1. 自动装瓶机控制系统设计概述在饮料、药品、日化等行业的包装生产线上,自动装瓶机是最关键的设备之一。传统人工灌装方式不仅效率低下,还容易造成产品污染和计量误差。我们团队基于西门子S7-1200 PLC开发的这套控制系统,实现了从空瓶输送到…

2026/10/13 7:32:14 阅读更多 →
JMeter压力测试实战:从电商下单场景到性能瓶颈定位

JMeter压力测试实战:从电商下单场景到性能瓶颈定位

1. 项目概述:为什么我们需要一个JMeter压力测试案例?如果你是一名后端开发、测试工程师或者运维,那么“压力测试”这个词对你来说一定不陌生。它就像给系统做一次全面的“体能检查”,在用户量激增、大促活动来临前,提前…

2026/9/29 20:19:17 阅读更多 →
【2027最新】基于SpringBoot+Vue的星之语明星周边产品销售网站管理系统源码+MyBatis+MySQL

【2027最新】基于SpringBoot+Vue的星之语明星周边产品销售网站管理系统源码+MyBatis+MySQL

博主介绍:✨ 专业背景 专注Java企业级开发与小程序生态,全网影响力10万开发者,CSDN特邀作者、技术专家、新星计划导师。 🎯 核心服务 📚 毕业设计智库 微信小程序方向:100个前沿选题 Java企业级方向&#x…

2026/10/6 21:25:25 阅读更多 →

最新新闻

Flutter同步方案鸿蒙化适配:CRDT冲突治理实践

Flutter同步方案鸿蒙化适配:CRDT冲突治理实践

如果你和我一样,正被“把一套 Flutter 同步方案搬到鸿蒙”这件事搞得焦头烂额,那这篇文章基本是为你准备的。最近我正好完成了一个基于 crdt_sync 的鸿蒙化适配项目,过程中把“同步资产”这几个字从口号拆成了实实在在的类、方法、通道和存储…

2026/10/13 7:32:05 阅读更多 →
Windows与Ubuntu双系统安装全攻略:从分区到引导修复

Windows与Ubuntu双系统安装全攻略:从分区到引导修复

看到“Windows系统上安装了Ubuntu”这句话,第一反应可能是:开机时多个选单,想进哪个进哪个。但落地时你很快会发现,这句话至少对应三种完全不同的结果——开机引导选单的双系统、Windows 窗口里跑的虚拟机、以及一条命令就能进的 …

2026/10/13 7:32:05 阅读更多 →
Linux用户与组管理实战:从基础原理到批量运维与安全加固

Linux用户与组管理实战:从基础原理到批量运维与安全加固

用户与组管理服务器刚到手、新同事入职、老同事离职、测试环境需要开个新账号……作为开发或运维,几乎每周都会跟用户与组管理打交道。这活儿看着简单,但真要深究,里面坑不少:建了账号忘了加组、权限给多了被安全部门点名、批量处…

2026/10/13 7:32:05 阅读更多 →
斗地主HTML5源码拆解:牌型引擎、AI与前端状态机

斗地主HTML5源码拆解:牌型引擎、AI与前端状态机

简介:《斗地主HTML5游戏源代码》是一份面向前端开发者和游戏学习者的完整实践资源,以人机对弈为核心玩法,展现从页面结构、界面美化到游戏规则判定与AI决策的完整开发链路,适合用作HTML5游戏入门及进阶的参考项目。压缩包共15个文…

2026/10/13 7:32:05 阅读更多 →
jstutorial 之 Page Visibility API:页面可见性检测与后台资源管控实战指南

jstutorial 之 Page Visibility API:页面可见性检测与后台资源管控实战指南

教程文档 【免费下载链接】jstutorial Javascript tutorial book 项目地址: https://gitcode.com/gh_mirrors/js/jstutorial 点击查看 免费下载 页面可见性是前端工程师最容易忽略、却在移动端与后台任务场景中至关重要的一环。本文以 jstutorial 仓库中 htmlapi/p…

2026/10/13 7:32:05 阅读更多 →
服务端模板注入(SSTI)深解析:从探测到防御实战指南

服务端模板注入(SSTI)深解析:从探测到防御实战指南

1. 从一条报错到服务器权限:SSTI注入到底是怎么发生的先聊个真实的场景。某次做安全评估,目标是一个看起来平平无奇的企业官网,功能是给用户提供在线文档模板生成。页面有个"输入姓名生成个性化欢迎页"的小功能,我随手输…

2026/10/13 7:31:05 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →