性能文章>记一次因烂代码引起的 OOM 事件>

记一次因烂代码引起的 OOM 事件原创

https://a.perfma.net/img/2521381
11月前
537905

本文正在参加「Java应用线上问题排查经验/工具分享」活动

背景

某天,公司某内部财务相关系统的研发找到我,说他们的系统内存只增不减,jmap 也看了没什么问题,弄的他们现在只能每几天重启一次避免服务挂掉……

问题描述

听起来像是内存泄露了,排查这种问题嘛,还是老一套,先看监控。

从 top 上看,该进程占用了 6G内存,可 jmap 的结果里,heap + noheap 一共也才不到 4G,难道还有 mmap/direct 之类的堆外内存?

然后通过 Arthas ,看了下堆外内存,也没有什么异常,数值很低……

这就有点奇怪了,JVM 实例所有内存(capacity)加起来也没这么多,那多余的 2G 内存哪去了呢?

而且这个研发还说,只要不重启服务,内存会一直增加,永远不会降低……

结合他描述的情况,很明显是内存泄露了,不过奇怪的是 heap + noheap 的总和加起来也没这么大,mmap/direct 也很低……内存去哪了呢?

此时我有点开始质疑自己了,难不成有什么更深层次的内存问题?就算是Netty 那块泄露了,也应该是 Direct 部分啊,多出的内存到底是哪来的……

冷静了几分钟之后,才反应过来。由于是内存问题,刚才看的一直是内存相关的指标,其他指标也得关注一下,毕竟这些指标都是有关联的。

于是我又看了眼该进程的线程情况,不看不知道,一看吓一跳……

这个服务进程竟然有好几千个线程……其中有 80% 都是 WAITING 状态

好了,这下应该是找到原因了,这么多线程,还都没在执行,内存不炸才奇怪呢。多半是滥用线程池,或者是手动创建线程,然后线程一直阻塞……

然后我指着这个数字,对研发小哥说:“你看这个接近 5 位数的线程总数,它美嘛?”

研发小哥看到这个数字之后,满脸尴尬的说:“我的错,我的错……”
image.png

我:“行吧,这明显是你们这个系统里线程用法不对,去检查一下所有使用线程池和手动创建线程的地方,看看有没有什么疑点,比如每次 new 线程池,用完不 shutdown 之类的……”

过了大概俩小时,这小哥回来了,说:“哥我找着了,跟你说的情况一样!有个菜鸡写的代码,每次 new 一个线程池去跑线程,用完还不 shutdown !”

“这个菜鸡是不是你?”

至此,问题解决……

总结

对于一些老系统里的屎山代码,出问题很正常,但凡一点变动就可能引起一些 Bug,而且由于代码过老,使用频率低,一般人还不敢动。

只能是遇一个坑,填一个坑,屎山代码可不是一般人能碰的了的东西……

分类:
标签:
请先登录,再评论

暂无回复,快来写下第一个回复吧~

为你推荐

字符串字面量长度是有限制的
前言 偶然在一次单元测试中写了一个非常长的字符串字面量。 正文 在一次单元测试中,我写了一个很长的字符串字面量,大概10万个字符左右,编译时,编译器给出了异常告警 `java: constant
多次字符串相加一定要用StringBuilder而不用-吗?
今天在写一个读取Java class File并进行分析的Demo时,偶然发现了下面这个场景(基于oracle jdk 1.8.0_144): ``` package test; public c
如何通过反射获得方法的真实参数名(以及扩展研究)
前段时间,在做一个小的工程时,遇到了需要通过反射获得方法真实参数名的场景,在这里我遇到了一些小小的问题,后来在部门老大的指导下,我解决了这个问题。通过解决这个问题,附带着我了解到了很多新的知识,我觉得
高吞吐、低延迟 Java 应用的 GC 优化实践
本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和
「每日五分钟,玩转 JVM」:久识你名,初居我心
聊聊 JVMJVM,一个熟悉又陌生的名词,从认识Java的第一天起,我们就会听到这个名字,在参加工作的前一两年,面试的时候还会经常被问到JDK,JRE,JVM这三者的区别。JVM可以说和我们是老朋友了
据说99.99%的人都会答错的类加载的问题
概述首先还是把问题抛给大家,这个问题也是我厂同学在做一个性能分析产品的时候碰到的一个问题。 同一个类加载器对象是否可以加载同一个类文件多次并且得到多个Class对象而都可以被java层使用吗请仔细注意
Java多线程——并发测试
编写并发程序时候,可以采取和串行程序相同的编程方式。唯一的难点在于,并发程序存在不确定性,这种不确定性会令程序出错的地方远比串行程序多,出现的方式也没有固定规则。那么如何在测试中,尽可能的暴露出这些问
Java多线程知识小抄集(一)
本文主要整理笔者遇到的Java多线程的相关知识点,适合速记,故命名为“小抄集”。本文没有特别重点,每一项针对一个多线程知识做一个概要性总结,也有一些会带一点例子,习题方便理解和记忆。 1.interr