这星期被线上JVM内存占用不断增大的问题所困扰,自己提出了一些假设,然后去实施验证都一一失败了,有一些经验和教训在这里分享下.

之所以是尴尬,是最后因为修复了另一个看似不相关的问题导致内存不再上升,但这之间的关系还未明了,还需要继续追踪.

这里讲述一下这次排查的过程.

直接内存的错误判断

服务器的JVM配置为Xmx3g,使用G1,没有设置Xms考虑自然收缩和fgc之后的空间回拢.

没有发生过fgc,且堆内存的增长正常,排除掉堆内存的问题.

使用NMT查看各个区域的内存正常,committed内存不足4G,但实际情况内存占用不断增大,甚至出现了OOM killer杀掉java进程.Total: reserved=5037MB, committed=3926MB

-                 Java Heap (reserved=3072MB, committed=3072MB)

(mmap: reserved=3072MB, committed=3072MB)-                     Class (reserved=1196MB, committed=192MB)

(classes #29793)

(malloc=6MB #86203)

(mmap: reserved=1190MB, committed=186MB)-                    Thread (reserved=186MB, committed=186MB)

(thread #184)

(stack: reserved=184MB, committed=184MB)

(malloc=1MB #922)

(arena=1MB #366)-                      Code (reserved=273MB, committed=171MB)

(malloc=29MB #39947)

(mmap: reserved=244MB, committed=142MB)-                        GC (reserved=176MB, committed=176MB)

(malloc=30MB #114115)

(mmap: reserved=146MB, committed=146MB)-                  Compiler (reserved=1MB, committed=1MB)-                  Internal (reserved=88MB, committed=88MB)

(malloc=88MB #83467)-                    Symbol (reserved=31MB, committed=31MB)

(malloc=27MB #312661)

(arena=4MB #1)-    Native Memory Tracking (reserved=10MB, committed=10MB)

(tracking overhead=10MB)-                   Unknown (reserved=6MB, committed=0MB)

(mmap: reserved=6MB, committed=0MB)

内存增长情况(中间下降是进行fgc或重启服务)

最开始考虑是直接内存的问题,观察GC行为发现没有发生过一次fgc,想当然觉得应该是直接内存无法回收,并且在手动执行gc之后内存占用的确是下降的.

于是调整了一波JVM参数,将堆大小设置为2500M,并配置MaxDirectMemory用来触发fgc.

但最后发现内存依旧增长,且还是没有fgc.

再观察了下heap(jmap -heap)的情况,发现手工触发fgc后,heap释放的大小和内存下降几乎一致.

在使用JMX查看了direct pool(java.nio.BufferPool)后惊奇地发现..直接内存并没有多少使用(我们底层用了netty,下意识认为出了问题):

图中所示最大只用了4M左右.

最后设置了Xms之后发现fgc已经没有作用,内存的使用量不会再下降,排除掉了这个因素.

这个错误的判断最主要的原因还是先入为主,没有收集支撑的直接证据.

stack中的间隙

接下去只能使用pmap(pamp -X pid)看下具体的内存信息.

发现了一些有趣的东西,大量的64M块.

直觉告诉我,快找出问题了.

搜索了下发现类似的问题:

解决方法也很直接换一个分配内存的库.

可选的也只有tcmalloc和jemalloc.

选择了前者,配置之后效果出众.

已经没有上图中那么多的64M块了.

并且启动后的内存使用是掉了下来,但是好景不长.

(蓝线是使用了tcmalloc,红线是对比方)

刚开始的确蓝线内存使用好一点(红线在20:00的时候重启 内存降低了).

但随后还是增长了,比较迷的一点是在8点后内存陡降(但JVM没有重启,PID也没有变化),恢复到了最初的水平.

看来问题不在这里.

看似没有关联的问题

周常部署的时候出现一个问题,导致heap OOM,我跟了下发现了一段代码内存溢出,但看似和这个堆外内存引起的问题没有关联就没怎么在意.

第二天同事修复了这个问题,迁移走了这个接口到另一个服务.

tcmalloc的heap profiling无法使用,一开启libunwind就segment fault退出,换成jemalloc后开启.

还在想是不是常见的那个zip溢出的问题,但是搜索了代码库没有发现忘记关闭的情况,等着看下增长和dump验证下.

观察了一会儿,突然发现内存不再增长了.

(蓝线是之前一直留着的机器,中间降低是进行了重启)

非常平稳地度过了一天.

那坨profiling也失去了意义... ...

这就感觉非常尴尬了...

继续追踪

更尴尬的是另一个服务炸了... ...

继续跟进,先把jemalloc配置过去,等下一次增长看下dump.

随着时间的推移遇见了各种各样的问题.

这次排查除了对之前积累的知识的运用,更多像是一次对搜索引擎熟练度的提升 :( .

但过程还是很不错的,也看到了一些自己以前没有接触过的知识.

深深感受到自己知识的匮乏,就像深渊(??)一样,逐渐深入才会发现不一样的风景.

生活中还是要多(xie)些bug才会更精彩的啊... ...

参考资料:

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

java没错泄露_记一次尴尬的Java应用内存泄露排查相关推荐

  1. java thread 内存泄露_记一次ThreadLocal引发的内存泄露

    概念 ​首先解释下内存溢出和内存泄露的概念.内存溢出一般指的是out of memory,也就是我们经常说的OOM,常发生在堆,方法区和方法栈.内存泄露指的是一段程序在申请内存空间后,无法释放已经申请 ...

  2. mongodb java 日志分析_记一次log4j与mongodb集成引发的问题分析

    问题背景 对项目中的关键应用调用链日志需要结构化得统一吐出到mongodb中,同时项目中日志输出使用log4j,故准备使用log4j的Appender直接集成mongodb的输出,同时mongodb采 ...

  3. java环境搭建_记一次阿里云服务器Java相关环境搭建的过程

    Java在Web开发中有着不可或缺的地位,在我们通常开发中,为了使编写的demo或者项目能够让更多的朋友看到,我们通常会将项目打包发布到网络中的服务器上,以便让更多的人访问到我们的劳动成果上.想着我们 ...

  4. java缓存内存泄漏_记一次mybaits缓存导致的内存溢出 java.lang.OutOfMemoryError: Java heap space...

    先贴一下错误截图 org.springframework.web.util.NestedServletException: Handler dispatch failed; nested except ...

  5. python会不会内存泄露_记一次python 内存泄漏问题及解决过程 python 嵌套读取文件 内存泄露...

    如何解决Python2的内存泄漏问题 python本身不会造成内存泄露,如果用的C/C++写的模块(包),如果处理不好,可能会造成内存泄露,但是也是C/C++的模块造成的 欢迎来到四十五资源网,pyt ...

  6. c++ socket线程池原理_一篇文章看懂 ThreadLocal 原理,内存泄露,缺点以及线程池复用的值传递问题...

    编辑:业余草来源:https://www.xttblog.com/?p=4946 一篇文章看懂 ThreadLocal 原理,内存泄露,缺点以及线程池复用的值传递问题. ThreadLocal 相信不 ...

  7. java 多重属性_最全面的44个Java 性能调优细节

    我认为,代码优化的最重要的作用应该是:避免未知的错误.在代码上线运行的过程中,往往会出现很多我们意想不到的错误,因为线上环境和开发环境是非常不同的,错误定位到最后往往是一个非常小的原因. 然而为了解决 ...

  8. 加载文件流_未关闭的文件流会引起内存泄露么?

    专注于Java领域优质技术,欢迎关注 来自:技术小黑屋 最近接触了一些面试者,在面试过程中有涉及到内存泄露的问题,其中有不少人回答说,如果文件打开后,没有关闭会导致内存泄露.当被继续追问,为什么会导致 ...

  9. java dispose事件_Android-在 ViewModel 中使用 AutoDispose2 解决 RxJava 的内存泄露问题

    RxJava 的内存泄露问题 runRxLambda 和 runRxLambdaViewModel 只是个扩展函数,可以不用理会,下面两段代码唯一的区别就是第二段增加了 AndroidLifecycl ...

最新文章

  1. php get安全字符,php安全之直接用$获取值而不$_GET 字符转义
  2. Gradle 配置spring boot启动
  3. 你能活多少岁,就让人工智能来告诉你吧
  4. 国际计算机杂志排名2015,中国计算机学会推荐国际学术刊物与期刊(新增列表)2015-12-22-06_48_31...
  5. 专题突破三之并查集Ⅱ——星球大战,In Touch,方格染色,Junk-Mail Filter,关押罪犯,Silver Woods,Must Be Rectangular!
  6. html缩进快捷键_Windows IDEA 快捷键终极大全,果断收藏!
  7. JavaScript 的 Date 方法的使用
  8. 斐波那契数列(Fibonacci)递归和非递归实现
  9. Android 中的数据储存方案, 持久化技术
  10. 2021年“泰迪杯”数据分析技能赛A题
  11. 随机信号分析学习笔记(6)
  12. Qt开发技术:Qt绘图系统(二)QPainter详解
  13. linux鼠标垫图片,如何自制智能游戏鼠标垫
  14. tampermonkey油猴实现自动定时刷新页面,刷访问量
  15. css画横线箭头_用纯CSS实现的箭头
  16. 教你怎么用手机进入路由器管理界面
  17. Windows中texstudio的主题代码(持续更新)
  18. Unity-live2D 实战篇笔记(背景音乐的设置,按钮触发的界面跳转)
  19. python做表格教程_表格函数教程
  20. mysql强制走索引

热门文章

  1. Python之urlparse模块
  2. 重磅!RTK差分共享猫APP即将开源!!
  3. Android 11 微信友盟分享报错 分享异常 Android 11及以上系统的手机需要使用FileProvider方式分享
  4. while循环和doWhile循环
  5. 进化论VS中性突变理论
  6. ZeroDivisionError:Integer division or modulo by zero
  7. 无符号数与带符号数的相加减
  8. AppScan 是一款web安全扫描工具
  9. Navicat Data Modeler(ndm2)数据模型逆向生成表
  10. ucosIII 共享资源(信号量、互斥信号量)