Java OOM 异常:从原理、场景、排查到解决方案全攻略
原理 → 场景 → 排查 → 解决方案面试 线上实战必备这是后端开发、测试、运维必须烂熟于心的终极 OOM 指南结构清晰、可直接用于复习、面试、故障处理。一、OOM 基础到底什么是 OOM1. 定义OOM OutOfMemoryErrorJVM 内存耗尽无法再分配新的内存空间且无法通过 GC 回收足够内存JVM 抛出致命错误。2. 本质原因内存真的不够数据量太大、堆太小内存泄漏对象不用了但 GC 无法回收资源未释放连接、流、缓存未关闭创建对象速度 GC 回收速度3. OOM 不是 Exception是 ErrorException可捕获、可恢复ErrorJVM 严重问题无法恢复二、OOM 6 大经典场景99% 线上故障都在这里1. Java Heap Space最常见plaintextjava.lang.OutOfMemoryError: Java heap space原因一次性加载太多数据如全表查询死循环创建对象集合对象只增不减缓存、List 无限增长内存泄漏典型代码java运行ListObject list new ArrayList(); while(true) list.add(new Object()); // 无限加2. Metaspace / PermGen 溢出plaintextjava.lang.OutOfMemoryError: Metaspace原因动态生成大量类CGLib、MyBatis、Groovy大量 JSP 编译成 Servlet反射 / 代理过多Metaspace 大小设置太小3. 栈溢出 StackOverflowErrorplaintextjava.lang.StackOverflowError原因递归死循环方法调用深度太深4. 直接内存溢出 Direct Buffer MemoryplaintextOutOfMemoryError: Direct buffer memory原因NIO 框架Netty使用堆外内存未释放直接缓冲区MaxDirectMemorySize 设置过小5. GC 开销过大plaintextjava.lang.OutOfMemoryError: GC overhead limit exceeded原因GC 回收效率极低98% 时间在 GC只回收 2% 内存JVM 保护性抛出异常6. 创建线程过多plaintextjava.lang.OutOfMemoryError: unable to create new native thread原因线程无限创建无池化OS 线程数上限被打满三、OOM 核心原理内存泄漏 vs 内存溢出1. 内存溢出OOM内存真的不够用了对象太多堆装不下。2. 内存泄漏Memory Leak对象不用了但 GC 无法回收越来越多垃圾堆积 → 最终 OOM3. 内存泄漏 7 大真凶静态集合static List/Map未关闭资源IO、Socket、Connection内部类持有外部类引用ThreadLocal 未 remove缓存未过期、未清理监听器未注销单例对象持有外部引用四、OOM 排查标准流程企业级实战第一步确认 OOM 类型看日志第一行Java heap space→ 堆溢出Metaspace→ 元空间溢出unable to create thread→ 线程过多第二步开启 JVM 自动 Dump必须配置plaintext-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/tmp/heap.hprofOOM 时自动导出堆快照不丢现场。第三步分析工具1. 命令行工具jps定位进程jstat -gc 12345看 GC 情况jmap手动 Dumpjstack看线程2. 可视化分析神器MATEclipse Memory Analyzer→ 最强Arthas→ 阿里开源线上实时诊断VisualVMJProfiler第四步MAT 快速定位泄漏打开.hprof文件点Leak Suspects看Problem Suspect定位到具体类、集合、对象查看 GC Roots 找到谁在引用第五步定位代码 → 修复五、OOM 标准解决方案通用万能方案1. 代码层治本避免死循环创建对象集合使用后清空 / 限制大小使用连接池DB、HTTP、Redis流、连接用完必须关闭ThreadLocal 必须remove()大集合分页处理缓存加过期、淘汰策略2. JVM 参数层治标plaintext# 堆内存 -Xms4g -Xmx4g # 元空间 -XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m # OOM自动dump -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/tmp/ # GC日志 -Xloggc:gc.log -XX:PrintGCDetails3. 架构层异步 限流分片、分页分布式缓存Redis服务拆分六、高频 OOM 场景 解决方案速查表表格OOM 类型典型原因最快解决方案Heap Space全表查询、死循环、内存泄漏分页、修复泄漏、加大 -XmxMetaspace大量动态类加大元空间、升级 ASM、检查 CGLibStackOverflow递归死循环修复递归、限制深度DirectBufferNIO 堆外内存未释放检查 Netty 配置增加 MaxDirectMemorySizeGC overhead内存快耗尽查泄漏、加大堆Unable to create thread无限制创建线程使用线程池、限制最大线程数七、面试必问 10 题标准答案1. OOM 是什么内存不足JVM 无法分配新对象。2. OOM 发生在哪些区域堆、元空间、栈、直接内存、线程栈。3. 内存泄漏和溢出的区别泄漏是占着不用溢出是真不够用。4. 哪些情况会导致内存泄漏静态集合、ThreadLocal、未关闭资源、内部类引用。5. 如何预防 OOM分页、池化、用完释放、加过期、限制集合大小。6. 线上 OOM 如何排查开启 Dump → MAT 分析 → 找 GC Roots → 定位代码。7. 最常见 OOMJava heap space。8. 如何让程序 OOM死循环往 List 加对象。9. 如何获取堆快照jmap 或 JVM 参数自动 Dump。10. 如何解决 OOM先代码修复泄漏再调整 JVM 参数。八、终极总结最强记忆版OOM 内存耗尽90% 是堆溢出80% 源于内存泄漏排查靠Dump MAT解决靠代码修复 JVM 参数线上必须加自动 Dump核心避免无限创建对象 用完及时释放
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2449699.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!