当前位置: 首页 > news >正文

《JVM如何排查OOM》

目录

一、什么是OOM?

二、OOM排查的整体思路

三、OOM排查工具大全

四、实战:不同OOM场景的排查方法

场景1:Java heap space

场景2:Metaspace

场景3:GC overhead limit exceeded

五、高级排查技巧

1. 使用Arthas进行在线诊断

2. 内存泄漏的Breadcrumb策略

3. 压力测试复现问题

六、预防OOM的最佳实践

七、真实案例分享

案例1:静态HashMap导致的内存泄漏

案例2:动态代理类撑爆Metaspace

八、总结

一、什么是OOM?

OOM(Out Of Memory)即内存溢出,是Java开发中最常见的错误之一。当JVM内存不足以分配对象空间,并且垃圾收集器也无法回收足够内存时,就会抛出java.lang.OutOfMemoryError错误。

常见的OOM错误类型包括:

  1. java.lang.OutOfMemoryError: Java heap space(堆内存不足)

  2. java.lang.OutOfMemoryError: Metaspace(元空间不足)

  3. java.lang.OutOfMemoryError: GC overhead limit exceeded(GC开销过大)

  4. java.lang.OutOfMemoryError: unable to create new native thread(无法创建新线程)

二、OOM排查的整体思路

确认错误类型:首先查看OOM的具体错误信息,确定是哪种类型的内存溢出

收集现场信息:在OOM发生时尽可能多地收集系统状态信息

分析内存使用:通过工具分析内存使用情况

定位问题代码:找到导致内存泄漏或过度消耗的代码

修复与验证:修复问题并验证解决方案的有效性

三、OOM排查工具大全

1. 命令行工具

jps - 查看Java进程

jps -l

jstat - 监控内存和GC情况

jstat -gcutil <pid> 1000 10 # 每1秒输出一次,共10次

jmap - 内存分析

jmap -heap <pid> # 查看堆内存配置和使用情况 
jmap -histo <pid> # 查看对象统计信息 
jmap -dump:format=b,file=heap.hprof <pid> # 生成堆转储文件

jstack - 线程分析

jstack <pid> > thread.txt

2. 可视化工具

VisualVM:JDK自带的可视化监控工具

MAT (Memory Analyzer Tool):强大的堆转储文件分析工具

JProfiler:商业级性能分析工具

Arthas:阿里开源的Java诊断工具

四、实战:不同OOM场景的排查方法

场景1:Java heap space

典型表现

java.lang.OutOfMemoryError: Java heap space

排查步骤

  1. 增加JVM参数收集信息:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof
  1. 使用jmap手动生成堆转储文件:
jmap -dump:format=b,file=heap.hprof <pid>

使用MAT分析堆转储文件:

查找占用内存最大的对象

查看对象的引用链

定位到具体的类和代码行

常见原因:

内存泄漏(对象被意外持有无法回收)

数据量确实过大(需要增加堆内存或优化程序)

场景2:Metaspace

典型表现

java.lang.OutOfMemoryError: Metaspace

排查步骤

查看元空间使用情况:

jstat -gc <pid>

调整JVM参数收集更多信息:

​​​​​​​-XX:+TraceClassLoading -XX:+TraceClassUnloading

常见原因:

动态生成大量类(如CGLib动态代理)

元空间设置过小(适当增加-XX:MaxMetaspaceSize

类加载器泄漏

场景3:GC overhead limit exceeded

典型表现

java.lang.OutOfMemoryError: GC overhead limit exceeded

排查步骤

查看GC日志:

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

分析GC效率:

关注GC频率和耗时

观察每次GC后的内存回收情况

常见原因:

堆内存设置过小

存在内存泄漏导致GC无法有效回收内存

对象存活时间配置不当

五、高级排查技巧

1. 使用Arthas进行在线诊断

# 启动Arthas 
java -jar arthas-boot.jar 
# 查看JVM内存情况 
dashboard
# 监控方法调用 
monitor -c 5 com.example.demo.Test testMethod 
# 查看对象引用 
vmtool --action getInstances --className java.lang.String --limit 10

2. 内存泄漏的Breadcrumb策略

定期(如每小时)执行jmap -histo:live <pid> > histo_$i.log

对比不同时间点的对象数量变化

找出异常增长的对象类型

3. 压力测试复现问题

使用JMeter或自定义脚本模拟高并发场景,配合以下JVM参数监控:

-XX:+PrintGCDetails 
-Xloggc:gc.log 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=./oom_dump.hprof

六、预防OOM的最佳实践

  1. 合理设置JVM参数

    • 根据应用特点设置初始(-Xms)和最大(-Xmx)堆内存
    • 新生代和老年代比例(-XX:NewRatio)
    • 设置元空间大小(-XX:MaxMetaspaceSize)
  2. 代码层面优化

    • 避免大对象长期存活
    • 及时关闭资源(数据库连接、文件流等)
    • 谨慎使用静态集合
    • 合理设计缓存策略
  3. 监控与告警

    • 实施JVM监控(如Prometheus + Grafana)
    • 设置内存使用阈值告警
    • 定期检查GC日志
  4. 定期演练

    • 模拟OOM场景进行演练
    • 验证监控告警的有效性
    • 测试团队对OOM的响应流程

七、真实案例分享

案例1:静态HashMap导致的内存泄漏

现象:应用运行几天后必现OOM

排查

  1. 堆转储分析显示HashMap占用了80%内存
  2. 追溯发现是全局静态HashMap缓存用户数据但从未清理
  3. 随着用户量增加,HashMap不断增长

解决

  1. 改用WeakHashMap或带过期策略的缓存
  2. 实现定期清理机制

案例2:动态代理类撑爆Metaspace

现象:高并发下频繁出现Metaspace OOM

排查

  1. 发现Metaspace使用量持续增长
  2. 分析类加载日志发现大量动态代理类
  3. 确认是框架为每个请求生成新代理类

解决

  1. 增加Metaspace大小
  2. 优化框架配置,启用代理类缓存

八、总结

OOM排查是Java开发者必备的技能,需要掌握:

  • 理解JVM内存模型和各区域作用
  • 熟练使用各种诊断工具
  • 建立系统化的排查思路
  • 积累常见场景的解决经验
  • 重视预防和监控,而非仅事后补救

记住:好的开发者不是不会遇到OOM,而是能够快速定位和解决OOM问题。希望本文能帮助你在遇到OOM时不再恐慌,而是有条不紊地解决问题。


文章转载自:

http://i1kQ6smN.xkzrt.cn
http://y1LOb2Sk.xkzrt.cn
http://71R25r9k.xkzrt.cn
http://OnFQEkmq.xkzrt.cn
http://isAuoING.xkzrt.cn
http://MRZqLwAX.xkzrt.cn
http://DEptBAQG.xkzrt.cn
http://2YwNjMxw.xkzrt.cn
http://faauYY2M.xkzrt.cn
http://uzDAO1V1.xkzrt.cn
http://Qg8yrGEd.xkzrt.cn
http://gYS8Prnn.xkzrt.cn
http://BI51iTao.xkzrt.cn
http://e11G4T2j.xkzrt.cn
http://2XOxohmN.xkzrt.cn
http://owBenk4r.xkzrt.cn
http://cevR0HC6.xkzrt.cn
http://Wud1hmXS.xkzrt.cn
http://nBNrNqIg.xkzrt.cn
http://9F0yyJoz.xkzrt.cn
http://AdlF9ppq.xkzrt.cn
http://5dSeiy1d.xkzrt.cn
http://rb78DgEU.xkzrt.cn
http://n9XGa3QM.xkzrt.cn
http://AGw4b2vZ.xkzrt.cn
http://33H1azjx.xkzrt.cn
http://UZ16YjQu.xkzrt.cn
http://rftKx7XK.xkzrt.cn
http://riDMHexT.xkzrt.cn
http://KtORsFrX.xkzrt.cn
http://www.dtcms.com/a/378013.html

相关文章:

  • ITP 3.0.0 版本重磅发布:接口测试平台迎来多项重大升级
  • 流式细胞术样本处理全攻略(一):组织、血液、体液制备方法详解
  • 【Ansible】将文件部署到受管主机知识点
  • 3 水平分表
  • ISO20000与IT运维和运营的关系
  • AI生成文本检测数据集:基于不平衡数据集(人类94% vs AI 6%)的高效机器学习模型训练,涵盖ChatGPT、Gemini等LLM生成内容
  • 音视频学习(六十四):avc1 hvc1和hev1
  • JC链客云——项目过程中获得的知识、遇到的问题及解决
  • 新手向:从零理解LTP中文文本处理
  • pyproject.toml 的历史背景和原理
  • vue知识点总结
  • macos arm自动编译x264和x265 Android平台so库
  • 三甲地市级医院数据仓湖数智化建设路径与编程工具选型研究(下)
  • Excel批量处理一列数据---分列功能
  • 从Miniflux 到 NextFlux:一步升级,拥抱现代化阅读体验
  • 机器视觉之图像处理篇
  • Find 命令详解
  • (九)Spring Cloud Alibaba 2023.x:微服务接口文档统一管理与聚合
  • 【C++深学日志】从0开始的C++生活
  • C#---Expression(表达式)
  • DCS控制回路优化:基于WebSocket的实时参数远程调校方法论
  • WebSocket压缩传输优化:机器视觉高清流在DCS中的低延迟方案
  • Java 软件测试(三):Mockito打桩与静态方法模拟解析
  • 大数据与AI:一场“数据盛宴”与“智能大脑”的奇妙邂逅
  • 前端学习之后端java小白(四)之数据库设计
  • 构建高效协作的桥梁:前后端衔接实践与接口文档规范详解
  • 基于 Vue+SQLite3开发吉他谱推荐网站
  • Skynet火焰图swt搭建
  • 临床数据挖掘与分析:利用GPU加速Pandas和Scikit-learn处理大规模数据集
  • InfoSecWarrior CTF 2020: 01靶场渗透