《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://www.pswp.cn/web/96504.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu22.04 安装Docker

一、更新系统包索引sudo apt update && sudo apt upgrade -y二、安装必要依赖安装 curl、gnupg等工具&#xff0c;用于添加 Docker 官方 GPG 密钥和仓库&#xff1a;sudo apt install -y ca-certificates curl gnupg三、添加 Docker 官方 GPG 密钥sudo install -m 0755…

高低压隔离器的技术演进与行业赋能

电力电子系统的安全架构与效率升级&#xff0c;始终依赖高低压电路间的可靠隔离。高低压隔离器作为能量传输与信号控制的核心媒介&#xff0c;通过持续迭代的绝缘技术与结构创新&#xff0c;为新能源装备、工业驱动系统提供底层安全屏障。其阻断电位差传导、抑制电磁干扰的能力…

嵌入式 - ARM5

一、led点灯代码优化1. 配置寄存器volatile1.​​禁止优化​​不对该变量的读写操作进行任何优化&#xff08;如删除“冗余”读取或延迟写入&#xff09;。2.​​强制内存访问​​每次访问该变量时&#xff0c;必须直接从内存&#xff08;或硬件寄存器&#xff09;中读取或写入…

SSH登录管理

两种配置方法-密码 -密钥&#xff08;免密&#xff09;ansible 默认 rhel9 禁止 root 用密码登陆&#xff0c;不禁止用密钥登陆 ---修改方式----vim /etc/ssh/sshd_config 修改此文件#PermitRootLogin prohibit-passwordPermitRootLogin yes 改为允许systemctl res…

远程连接--向日葵

下载安装卸载 向日葵语言设置 点击下面的图标,点击"设置": 问题解决 向日葵被连接之后自动黑屏 取消下面的勾选框: 向日葵连接之后黑屏 检查系统的协议: echo $XDG_SESSION_TYPE 如果是: wayland 需要切换为x11. 设置永久默认使用 X11: sudo vi /etc/gdm3/custom…

Liunx执行source /etc/profile 报错, -bash: HISTTIMEFORMAT: readonly variable

今天在配置java环境变量时&#xff0c;执行source /etc/profile报错&#xff0c;系统是统信OS&#xff0c;花了好长时间才解决&#xff0c;在这记录一下&#xff0c;希望能帮助到大家问题截图提示HISTTIMEFORMAT和PROMPT_COMMAND变量时只读变量&#xff0c;不能设置属性值解决办…

什么是达林顿管?

简单来说&#xff0c;达林顿管是一个“电流放大器中的大力士”。它的核心目的是用非常小的输入电流&#xff08;基极电流&#xff09;去控制一个非常大的输出电流&#xff08;集电极电流&#xff09;。达林顿管是由两个三极管串联而成&#xff0c;放大倍数是两个三极管的放大倍…

嵌入式Linux学习_rk3588移植无线网卡驱动

记录移植无线网卡驱动遇到的各种问题&#xff1a; 从官网上下载8821的驱动源码复制一份上面的CONFIG_PLATFORM_ARM_RK2818&#xff0c;改成3588&#xff0c;然后选项改成y&#xff0c;并把autodetect关掉。 找到CONFIG_PLATFORM_ARM_RK2818&#xff0c;复制一份&#xff0c;改成…

MCP专题五、MCP 的未来趋势与展望

MCP专题五:MCP 的未来趋势与展望 5.1 引言 本专题前四章我们系统性地学习了 MCP(Model Context Protocol)的 发展背景、核心机制、Python 实战方法以及典型应用场景。可以看到,MCP 并不仅仅是一个技术标准,它更像是 大模型与外部世界沟通的桥梁,推动了 AI 应用从“实验…

C++ Dijkstra堆优化算法

时间复杂度为&#xff1a;O((nm)logn)算法特点&#xff1a;非负边权、单源最短路、顶点数、边数<1000000&#xff0c;数据结构前置&#xff1a;领接表、哈希表、二叉堆算法&#xff1a;第一步&#xff0c;建图&#xff0c;任何算法我们都要去思考&#xff0c;用什么数据结构…

网页设计作业02

<!DOCTYPE html> <html> <head><meta charset"utf-8"/><title>网页设计作业</title> </head> <body><h2>问卷调查</h2><p><strong>1、你是通过什么途径来到绿叶学习网的&#xff1f;</s…

每日算法题推送-->今日专题——双指针法

题目1&#xff1a;https://leetcode.cn/problems/move-zeroes 小编刚看到这道题的时候&#xff0c;想到的第一个方法就是建立一个与原数组等大的新的数组&#xff0c;然后遍历原数组&#xff0c;如果遇到元素值不为0的元素&#xff0c;就将这个元素放到新数组中&#xff0c;直到…

告别单次对话:上下文工程如何重塑AI应用架构

1. 前言人工智能应用开发领域正在经历一场静悄悄的变革。去年此时&#xff0c;提示工程&#xff08;Prompt Engineering&#xff09;还是各大技术论坛的热门话题&#xff0c;开发者们热衷于分享各种精心设计的提示词模板&#xff0c;试图通过单次交互获得理想的大模型输出。然而…

PM2 管理后端(设置项目自启动)

查看pm2管理pm2 list ┌────┬──────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──…

CCN中商再获三项知识产权,为数字化服务添动能

上海中商网络股份有限公司&#xff08;CCN中商&#xff09;依托持续的研发投入与深厚的技术积淀&#xff0c;在知识产权领域再获重要突破——成功收获三项知识产权&#xff0c;囊括实用新型专利《一种3D霓彩智感双条光柱印刷用全自动生产线》、发明专利《一种一物一码关联系统及…

使用LTspice仿真一个异步BUCK电路

确定异步BUCK的规格 输入电压&#xff08;Vin&#xff09;&#xff1a;12V 输出电压&#xff08;Vout&#xff09;&#xff1a;6V 最大输出电流&#xff08;Iout&#xff09;&#xff1a;3A 开关频率&#xff08;fsw&#xff09;&#xff1a;400kHz 输出电压纹波&#xff08;Δ…

R语言对excel中多个sheet子表批量进行地理探测器计算

## 基本设置 ## 1) 设定你的工作目录&#xff08;保持你的原路径不变&#xff09; setwd("D:/*****/*****/******")## 2) 文件名&#xff08;与xlsx实际名字保持一致&#xff09; xlsx_file <- "驱动因素&#xff08;中低收入&#xff09;.xlsx"## 依…

C++ JSON 数据库:jsoncpp

jsoncpp1. JSON数据1.1 JSON 的基本语法规则1. 基础语法要求两种核心数据结构JSON 与其他数据格式的对比1.2 JSON 的典型应用场景1.3 JSON 解析与生成工具2. 编程语言库&#xff08;解析/生成&#xff09;1.4 常见错误与注意事项2. jsoncpp2.1 基本用法1. 安装与集成2. 核心类与…

《苍穹外卖》项目日记_Day9

前言&#xff1a; 上午就把今天任务完成了&#xff0c;就继续往后学了一些知识&#xff0c;晚上写下笔记总结一下。 今日完成任务&#xff1a; 调用百度地图开放平台&#xff0c;优化用户下单业务学习SpringTask&#xff0c;定时处理超时、派送中订单学习WebSocket&#xff0c;…

人工智能学习:Transformer结构中的编码器层(Encoder Layer)

Transformer结构中的编码器层(Encoder Layer) 一、编码器层介绍 概念 编码器层(Encoder Layer)是Transformer编码器的基本构建单元,它重复堆叠形成整个编码器,负责逐步提取输入序列的特征。每个编码器层由两个核心子层组成: 多头自注意力机制(Multi-Head Self-Attentio…