为什么80%的码农都做不了架构师?>>>   

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/196user@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: #进程IDNative 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'`.txtpmap -x ${COLLECTOR_PID} > ${OUTDIR}/${HOSTNAME}_coll_${COLLECTOR_PID}_pmap_`date '+%Y%m%d_%H%M%S'`.txt

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

验证后发现问题和JDK8的一个bug https://bugs.java.com/view_bug.do?bug_id=8180048 非常类似,测试后也证实确实如此,最后通过升级JDK解决了这个问题。具体是那个组件命中了JDK的这个bug,会在下一篇文章中详细描述。

转载于:https://my.oschina.net/foxty/blog/1934968

JVM NativeMemoryTracking 分析堆外内存泄露相关推荐

  1. java 监控 native 内存_JVM NativeMemoryTracking 分析堆外内存泄露

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

  2. pmap gdb 分析堆外内存泄露情况

    一.查看内存分部  pmap -x 8 | sort -k3 -n -r | more       ----  8 是  PID 最大的肯定是堆内存. 其他的就需要看情况来分析了. 二.cat /pr ...

  3. Netty堆外内存泄露排查与总结

    导读 Netty 是一个异步事件驱动的网络通信层框架,用于快速开发高可用高性能的服务端网络框架与客户端程序,它极大地简化了 TCP 和 UDP 套接字服务器等网络编程. Netty 底层基于 JDK ...

  4. 一次堆外内存泄露的排查过程

    转载自  一次堆外内存泄露的排查过程 最近在做一个基于 websocket 的长连中间件,服务端使用实现了 socket.io 协议(基于websocket协议,提供长轮询降级能力) 的 netty- ...

  5. Netty堆外内存泄露排查盛宴

    导读 Netty 是一个异步事件驱动的网络通信层框架,用于快速开发高可用高性能的服务端网络框架与客户端程序,它极大地简化了 TCP 和 UDP 套接字服务器等网络编程. Netty 底层基于 JDK ...

  6. Netty堆外内存泄露排查与总结 1

    导读 Netty 是一个异步事件驱动的网络通信层框架,用于快速开发高可用高性能的服务端网络框架与客户端程序,它极大地简化了 TCP 和 UDP 套接字服务器等网络编程. Netty 底层基于 JDK ...

  7. 如何分析堆外内存使用情况_堆上与堆外的内存使用情况

    如何分析堆外内存使用情况 总览 最近有人问我在Java中使用堆内存的好处和智慧. 面临相同选择的其他人可能会对这些答案感兴趣. 堆外内存没什么特别的. 线程堆栈,应用程序代码,NIO缓冲区都在堆外. ...

  8. JVM初探- 使用堆外内存减少Full GC

    JVM初探-使用堆外内存减少Full GC 标签 : JVM 问题: 大部分主流互联网企业线上Server JVM选用了CMS收集器(如Taobao.LinkedIn.Vdian), 虽然CMS可与用 ...

  9. Java堆外内存泄露分析

    查看堆内存占用正常,jvm垃圾回收也没有异常.而top出来显示java占用内存是几个G,那么可能想到了是堆外内存泄漏. 需要安装google-perftools工具进行分析 1.先安装g++ 不然编译 ...

最新文章

  1. 如何通过参数来切换图表和数据
  2. ffmpeg推送图片到流媒体服务器
  3. java安全沙箱(一)之ClassLoader双亲委派机制
  4. linux文件句柄,【LINUX】使用lsof处理文件恢复、句柄以及空间释放问题
  5. 福建三明市梅列区巧用“智慧梅列” 助推重大项目建设
  6. 5_Windows下利用批处理切换IP地址
  7. 为什么eolinker发送老是等待_eolinker之初体验
  8. python生成随机数random操作_Python random生成随机数示例
  9. DM6467T开发板领航——开发环境
  10. motion blur matlab,Motion Blur app
  11. 风控中英文术语手册(银行_消费金融信贷业务)_version6
  12. SpringCloud 微服务视频教程
  13. AD15如何在PCB界面锁定选中元件
  14. python pdb模块_Biopython PDB模块
  15. IT与商业管理的三大阶段
  16. 高通平台文档下载【学习笔记】
  17. js 文件下载请求两种方式
  18. 用Navicat连接阿里云数据库RDS
  19. PE和CDlinux二合一启动盘制作
  20. 【计算机网络学习笔记13】交换技术(下)

热门文章

  1. web从零单排,做一个简单的幻灯片
  2. Marcin Grzejszczak访谈:Spring Cloud Contract
  3. ossec 学习二 (ossec -analogi安装)
  4. C++primer笔记之关联容器
  5. linux 常用的系统信息查看命令
  6. python基础:购物车的简单实现
  7. Python的装饰器
  8. JForum 的 SSO集成
  9. Linux下 memcached安装以及启动
  10. dedecms调用当前栏目ID与当前栏目顶级ID的方法