百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

一次完整的JVM NativeMemoryTracking 堆外内存泄露分析

yuyutoo 2024-10-11 23:55 1 浏览 0 评论

Native Memory Tracking (NMT) 是Hotspot VM用来分析VM内部内存使用情况的一个功能。我们可以利用jcmd(jdk自带)这个工具来访问NMT的数据。

NMT介绍

工欲善其事必先利其器,我们先把相关需要的配置和工具介绍清楚,再通过例子来看看具体如何使用NMT。

打开NMT

NMT必须先通过VM启动参数中打开,不过要注意的是,打开NMT会带来5%-10%的性能损耗。

-XX:NativeMemoryTracking=[off | summary | detail]
# off: 默认关闭
# summary: 只统计各个分类的内存使用情况.
# detail: Collect memory usage by individual call sites.

jcmd查看NMT报告

通过jcmd查看NMT报告以及查看对比情况。

jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]

# summary: 分类内存使用情况.
# detail: 详细内存使用情况,除了summary信息之外还包含了虚拟内存使用情况。
# baseline: 创建内存使用快照,方便和后面做对比
# summary.diff: 和上一次baseline的summary对比
# detail.diff: 和上一次baseline的detail对比
# shutdown: 关闭NMT

VM退出时打印NMT

可以通过下面VM参数在JVM退出时打印NMT报告。

-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

NMT实战

症状

某个服务(C)在客户环境使用后发现其内存占用不断变大且远超Xmx指定的大小,导致整个系统因缺少内存造成其他服务无法启动。当时查看到其RSS大约为11G,-Xmx=6G而且heap利用率不到50%。

user@hostxxx> prstat -p 2780
PID USERNAME  SIZE   RSS   STATE  PRI   NICE  TIME     CPU   PROCESS/NLWP
2780 user    11G     11G   sleep   59    0    44:16:39 0.0%  java/196

user@hostxxx> /opt/jdk1.8.0_40/bin/jstat -gcutil 2780
S0     S1     E      O      M     CCS    YGC     YGCT       FGC    FGCT     GCT
0.00 100.00  90.60  46.80  98.02  97.10  11323   4049.745   11     225.345   4275.090

分析

服务通过-Xmx=6G指定最大堆分配为6G,但实际RSS已达到11G,开始怀疑堆外内存是否有内存泄露。为了有更好详细的数据,就在本地重现这个问题,并且打开了NMT持续监控。

NMT的Report如下,重点关注每个分类下的commit大小,这个是实际使用的内存大小。

6739: #进程ID

Native Memory Tracking:

Total: reserved=8491110KB, committed=7220750KB
-                 Java Heap (reserved=6293504KB, committed=6291456KB) 
                            (mmap: reserved=6293504KB, committed=6291456KB) 
 
-                     Class (reserved=1107429KB, committed=66189KB) 
                            (classes #11979)
                            (malloc=1509KB #18708) 
                            (mmap: reserved=1105920KB, committed=64680KB) 
 
-                    Thread (reserved=159383KB, committed=159383KB) 
                            (thread #156)
                            (stack: reserved=158720KB, committed=158720KB)
                            (malloc=482KB #788) 
                            (arena=182KB #310)
 
-                      Code (reserved=255862KB, committed=41078KB) 
                            (malloc=6262KB #9319) 
                            (mmap: reserved=249600KB, committed=34816KB) 
 
-                        GC (reserved=449225KB, committed=449225KB) 
                            (malloc=166601KB #1714646) 
                            (mmap: reserved=282624KB, committed=282624KB) 
 
-                  Compiler (reserved=395KB, committed=395KB) 
                            (malloc=265KB #856) 
                            (arena=131KB #3)
 
-                  Internal (reserved=146041KB, committed=146041KB) 
                            (malloc=132185KB #276370) 
                            (mmap: reserved=13856KB, committed=13856KB) 
 
-                    Symbol (reserved=31487KB, committed=31487KB) 
                            (malloc=29209KB #91080) 
                            (arena=2278KB #1)
 
-    Native Memory Tracking (reserved=33212KB, committed=33212KB) 
                            (malloc=168KB #2575) 
                            (tracking overhead=33044KB)
 
-               Arena Chunk (reserved=2284KB, committed=2284KB)
                            (malloc=2284KB) 
 
-                   Unknown (reserved=12288KB, committed=0KB)
                            (mmap: reserved=12288KB, committed=0KB) 
 
Virtual memory map:
......

并且在服务器上通过cron job来定期抓取NMT的report保存下来做分析,而且同时也把其对应的RSS和PMAP都抓取了一份。

COLLECTOR_PID=`ps -ef|grep "ProcessName" | grep -v grep | awk '{print $2}'`
OUTDIR=/opt/chkmem
HOSTNAME=`hostname`

prstat -s rss 1 1 > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_prstat_`date '+%Y%m%d_%H%M%S'`.txt

/opt/jdk1.8.0_40/bin/jcmd ${COLLECTOR_PID} VM.native_memory detail > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_nmd_`date '+%Y%m%d_%H%M%S'`.txt

pmap -x ${COLLECTOR_PID} > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_pmap_`date '+%Y%m%d_%H%M%S'`.txt

分析发现NMT中的Symbol域持续增大,从最开始的几十兆已经增加到了2G左右,而且整个jvm的内存使用量也在持续增加。见下图:

验证后发现问题和JDK8的bug非常类似,测试后也证实确实如此,最后通过升级JDK解决了这个问题。 导致这个问题的组件是Jackson Streaming API 中的 JsonFactory.Feature.INTERN_FIELD_NAMES 引起的,由于项目中需要大量解析动态json文件,并且key都被intern到JVM native 内存无法释放导致内存泄露。

相关推荐

jQuery VS AngularJS 你更钟爱哪个?

在这一次的Web开发教程中,我会尽力解答有关于jQuery和AngularJS的两个非常常见的问题,即jQuery和AngularJS之间的区别是什么?也就是说jQueryVSAngularJS?...

Jquery实时校验,指定长度的「负小数」,小数位未满末尾补0

在可以输入【负小数】的输入框获取到焦点时,移除千位分隔符,在输入数据时,实时校验输入内容是否正确,失去焦点后,添加千位分隔符格式化数字。同时小数位未满时末尾补0。HTML代码...

如何在pbootCMS前台调用自定义表单?pbootCMS自定义调用代码示例

要在pbootCMS前台调用自定义表单,您需要在后台创建表单并为其添加字段,然后在前台模板文件中添加相关代码,如提交按钮和表单验证代码。您还可以自定义表单数据的存储位置、添加文件上传字段、日期选择器、...

编程技巧:Jquery实时验证,指定长度的「负小数」

为了保障【负小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【负小数】的方法。HTML代码<inputtype="text"class="forc...

一篇文章带你用jquery mobile设计颜色拾取器

【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...

编程技巧:Jquery实时验证,指定长度的「正小数」

为了保障【正小数】的正确性,做成了通过Jquery,在用户端,实时验证指定长度的【正小数】的方法。HTML做成方法<inputtype="text"class="fo...

jquery.validate检查数组全部验证

问题:html中有多个name[],每个参数都要进行验证是否为空,这个时候直接用required:true话,不能全部验证,只要这个数组中有一个有值就可以通过的。解决方法使用addmethod...

Vue进阶(幺叁肆):npm查看包版本信息

第一种方式npmviewjqueryversions这种方式可以查看npm服务器上所有的...

layui中使用lay-verify进行条件校验

一、layui的校验很简单,主要有以下步骤:1.在form表单内加上class="layui-form"2.在提交按钮上加上lay-submit3.在想要校验的标签,加上lay-...

jQuery是什么?如何使用? jquery是什么功能组件

jQuery于2006年1月由JohnResig在BarCampNYC首次发布。它目前由TimmyWilson领导,并由一组开发人员维护。jQuery是一个JavaScript库,它简化了客户...

django框架的表单form的理解和用法-9

表单呈现...

jquery对上传文件的检测判断 jquery实现文件上传

总体思路:在前端使用jquery对上传文件做部分初步的判断,验证通过的文件利用ajaxFileUpload上传到服务器端,并将文件的存储路径保存到数据库。<asp:FileUploadI...

Nodejs之MEAN栈开发(四)-- form验证及图片上传

这一节增加推荐图书的提交和删除功能,来学习node的form提交以及node的图片上传功能。开始之前需要源码同学可以先在git上fork:https://github.com/stoneniqiu/R...

大数据开发基础之JAVA jquery 大数据java实战

上一篇我们讲解了JAVAscript的基础知识、特点及基本语法以及组成及基本用途,本期就给大家带来了JAVAweb的第二个知识点jquery,大数据开发基础之JAVAjquery,这是本篇文章的主要...

推荐四个开源的jQuery可视化表单设计器

jquery开源在线表单拖拉设计器formBuilder(推荐)jQueryformBuilder是一个开源的WEB在线html表单设计器,开发人员可以通过拖拉实现一个可视化的表单。支持表单常用控件...

取消回复欢迎 发表评论: