java 堆外内存 查看_JAVA堆外内存排查小结

本文详述了一次针对Java服务堆外内存异常增长的排查过程,涉及pmap、gdb、perf等工具的使用,发现问题是由于GZIPInputStream未正确关闭导致的bzip内存泄漏。解决方案是确保及时关闭流以释放堆外内存。
摘要由CSDN通过智能技术生成

简介JVM堆外内存难排查但经常会出现问题,这可能是目前最全的JVM堆外内存排查思路。

通过本文,你应该了解:pmap 命令

gdb 命令

perf 命令

内存 RSS、VSZ的区别

java NMT

起因

这几天遇到一个比较奇怪的问题,觉得有必要和大家分享一下。我们的一个服务,运行在docker上,在某个版本之后,占用的内存开始增长,直到docker分配的内存上限,但是并不会OOM。版本的更改如下:升级了基础软件的版本

将docker的内存上限由4GB扩展到8GB

上上个版本的一项变动是使用了EhCache的Heap缓存

没有读文件,也没有mmap操作

使用jps 查看启动参数,发现分配了大约3GB的堆内存

[root]$ jps -v

75 Bootstrap -Xmx3000m -Xms3000m -verbose:gc -Xloggc:/home/logs/gc.log -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSCompactAtFullCollection -XX:MaxTenuringThreshold=10 -XX:MaxPermSize=128M -XX:SurvivorRatio=3 -XX:NewRatio=2 -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseParNewGC -XX:+UseConcMarkSweepGC

使用ps查看进程使用的内存和虚拟内存 ( Linux内存管理 )。除了虚拟内存比较高达到17GB以外,实际使用的内存RSS也夸张的达到了7GB,远远超过了-Xmx的设定。

[root]$ ps -p 75 -o rss,vsz

RSS VSZ 7152568 17485844

排查过程

明显的,是有堆外内存的使用,不太可能是由于EhCache引起的(因为我们使用了heap方式)。了解到基础软件的升级涉及到netty版本升级,netty会用到一些DirectByteBuffer,第一轮排查我们采用如下方式:jmap -dump:format=b,file=75.dump 75 通过分析堆内存找到DirectByteBuffer的引用和大小

部署一个升级基础软件之前的版本,持续观察

部署另一个版本,更改EhCache限制其大小到1024M

考虑到可能由Docker的内存分配机制引起,部署一实例到实体机

结果4个环境中的服务,无一例外的都出现了内存超用的问题。问题很奇怪,宝宝睡不着觉。

pmap

为了进一步分析问题,我们使用pmap查看进程的内存分配,通过RSS升序序排列。结果发现除了地址000000073c800000上分配的3GB堆以外,还有数量非常多的64M一块的内存段,还有巨量小的物理内存块映射到不同的虚拟内存段上。但到现在为止,我们不知道里面的内容是什么,是通过什么产生的。

[root]$ pmap -x 75 | sort -n -k3

.....省略N行

00000000

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值