0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用NMT和pmap来解决JVM的资源泄漏问题

openEuler 来源:openEuler 作者:宋尧飞 2021-09-24 16:00 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

编者按:笔者使用 JDK 自带的内存跟踪工具 NMT 和 Linux 自带的 pmap 解决了一个非常典型的资源泄漏问题。这个资源泄漏是由于 Java 程序员不正确地使用 Java API 导致的,使用 Files.list 打开的文件描述符必须关闭。本案例一方面介绍了怎么使用 NMT 解决 JVM 资源泄漏问题,如果读者遇到类似问题,可以尝试用 NMT 来解决;另一方面也提醒 Java 开发人员使用 Java API 时需要必须弄清楚 API 使用规范,希望大家通过这个案例有所收获。

背景知识:

NMT

NMT 是 Native Memory Tracking 的缩写,一个 JDK 自带的小工具,用来跟踪 JVM 本地内存分配情况(本地内存指的是 non-heap,例如 JVM 在运行时需要分配一些辅助数据结构用于自身的运行)。

NMT 功能默认关闭,可以在 Java 程序启动参数中加入以下参数来开启:

-XX:NativeMemoryTracking=[summary | detail]

其中,“summary” 和 “detail” 的差别主要在输出信息的详细程度。

3cb43d90-10ac-11ec-8fb8-12bb97331649.png

开启 NMT 功能后,就可以使用 JDK 提供的 jcmd 命令来读取 NMT 采集的数据了,具体命令如下:

jcmd 《pid》 VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown]

NMT 参数的含义可以通过 “jcmd 《pid》 help VM.native_memory” 命令查询。通过 NMT 工具,我们可以快速区分内存泄露是否源自 JVM 分配。

pmap

对于非 JVM 分配的内存,经常需要用到 pmap 这个工具了,这是一个 linux 系统自带工具,能够从系统层面输出目标进程内存使用的详细情况,用法非常简单:

pmap [参数] 《pid》

常用的选项是 “-x” 或 “-X”,都是用来控制输出信息的详细程度。

上图是 pmap 部分输出信息,每列含义为

pYYBAGFNe46AXEijAACM5oGR0ow649.png

现象:

某业务集群中,多个节点出现业务进程内存消耗缓慢增长现象,以其中一个节点为例:

3cd60e48-10ac-11ec-8fb8-12bb97331649.png

如图所示,这个业务进程当前占用了 4.7G 的虚拟内存空间,以及 2.2G 的物理内存。已知正常状态下该业务进程的物理内存占用量不超过 1G。

分析:

使用命令 “jcmdVM.native_memory detail” 可以看到所有受 JVM 监控的内存分布情况:

3cfaa4e2-10ac-11ec-8fb8-12bb97331649.png

上图只是截取了 nmt(Native Memory Tracking) 命令展示的概览信息,这个业务进程占用的 2.2G 物理内存中,受 JVM 监控的大概只占了 0.7G(上图中的 committed),意味着有 1.5G 物理内存不受 JVM 管控。JVM 可以监控到 Java 堆、元空间、CodeCache、直接内存等区域,但无法监控到那些由 JVM 之外的 Native Code 申请的内存,例如典型的场景:第三方 so 库中调用 malloc 函数申请一块内存的行为无法被 JVM 感知到。

nmt 除了会展示概览之外,还会详细罗列每一片受 JVM 监控的内存,包括其地址,将这些 JVM 监控到的内存布局和用 pmap 得到的完整的进程内存布局做一个对比筛查,这里忽略 nmt 和 pmap(下图 pmap 命令中 25600 是进程号)详细内存地址的信息,直接给出最可疑的那块内存:

3d0e578a-10ac-11ec-8fb8-12bb97331649.png

由图可知,这片 1.7G 左右的内存区域属于系统层面的堆区。

备注:这片系统堆区之所以稍大于上面计算得到的差值,原因大概是 nmt 中显示的 committed 内存并不对应真正占用的物理内存(linux 使用 Lazy 策略管理进程内存),实际通常会稍小。

系统堆区主要就是由 libc 库接口 malloc 申请的内存组合而成,所以接下来就是去跟踪业务进程中的每次 malloc 调用,可以借助 GDB:

3d235a5e-10ac-11ec-8fb8-12bb97331649.png

实际上会有大量的干扰项,这些干扰项一方面来自 JVM 内部,比如:

3d3cc782-10ac-11ec-8fb8-12bb97331649.png

这部分干扰项很容易被排除,凡是调用栈中存在 “os::malloc” 这个栈帧的干扰项就可以直接忽视,因为这些 malloc 行为都会被 nmt 监控到,而上面已经排除了受 JVM 监控内存泄漏的可能。

另一部分干扰项则来自 JDK,比如:

3d6b9ee0-10ac-11ec-8fb8-12bb97331649.png

有如上图所示,不少 JDK 的本地方法中直接或间接调用了 malloc,这部分 malloc 行为通常是不受 JVM 监控的,所以需要根据具体情况逐个排查,还是以上图为例,排查过程如下:

3dac2b22-10ac-11ec-8fb8-12bb97331649.png

注意图中临时中断的值(0x0000ffff5fc55d00)来自于第一个中断 b malloc 中断发生后的结果。

这里稍微解释一下上面 GDB 在做的排查过程,就是检查 malloc 返回的内存地址后续是否有通过 free 释放(通过 tb free if X3 这个命令,具体用法可以参考 GDB 调试),显然在这个例子中是有释放的。

通过这种排查方式,几经筛选,最终找到了一个可疑的 malloc 场景:

3dbaf18e-10ac-11ec-8fb8-12bb97331649.png

从调用栈信息可以知道,这是一个 JDK 中的本地方法 sun.nio.fs.UnixNativeDispatcher.opendir0,作用是打开一个目录,但后续始终没有进行关闭操作。进一步分析可知,该可疑 opendir 操作会周期性执行,而且都是操作同一个目录 “/xxx/nginx/etc/nginx/conf”,看来,是有个业务线程在定时访问 nginx 的配置目录,每次访问完却没有关闭打开的目录。

分析到这里,其实这个问题已经差不多水落石出。和业务方确认,存在一个定时器线程在周期性读取 nginx 的配置文件,代码大概是这样子的:

3dfba080-10ac-11ec-8fb8-12bb97331649.png

翻了一下相关 JDK 源码,Files.list 方法是有在末尾注册一个关闭钩子的:

3e0bb2b8-10ac-11ec-8fb8-12bb97331649.png

也就是说,Files.list 方法返回的目录资源是需要手动释放的,否则就会发生资源泄漏。

由于这个目录资源底层是会关联一个 fd 的,所以泄漏问题还可以通过另一个地方进行佐证:

3e3fafaa-10ac-11ec-8fb8-12bb97331649.png

该业务进程目前已经消耗了 51116 个 fd!

假设这些 fd 都是 opendir 关联的,每个 opendir 消耗 32K,则总共消耗 1.6G,显然可以跟上面泄漏的内存值基本对上。

总结:

稍微了解了一下,发现几乎没人知道 JDK 方法 Files.list 是需要关闭的,这个案例算是给大家都提了个醒。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11810

    浏览量

    219513
  • 源码
    +关注

    关注

    8

    文章

    689

    浏览量

    31459
  • JVM
    JVM
    +关注

    关注

    0

    文章

    161

    浏览量

    13084
  • JDK
    JDK
    +关注

    关注

    0

    文章

    83

    浏览量

    17192

原文标题:使用 NMT 和 pmap 解决 JVM 资源泄漏问题

文章出处:【微信号:openEulercommunity,微信公众号:openEuler】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    CANopen协议核心秘籍:NMT、SDO、PDO、心跳报文一网打尽

    工程师必备:从状态切换、参数配置到实时数据传输,一篇搞定CANopen通信难题CANopen协议在工业自动化中无处不在,但复杂的对象字典、多样的报文类型常让开发者头疼。本文将NMT网络管理、SDO
    的头像 发表于 03-05 19:34 458次阅读
    CANopen协议核心秘籍:<b class='flag-5'>NMT</b>、SDO、PDO、心跳报文一网打尽

    Microchip MTCH9010泄漏检测器助力医疗设备安全升级

    在医疗设备的安全设计中,液体泄漏检测常常被忽视,但它却是守护设备稳定运行和患者安全的关键一环。Microchip的MTCH9010泄漏检测器,正如专家博文《Microchip的MTCH9010泄漏
    的头像 发表于 01-07 16:41 742次阅读

    化工厂液体泄漏识别预警系统

    化工厂液体泄漏识别预警系统基于人工智能分析技术,化工厂液体泄漏识别预警系统自动识别监控视频中机械管道是否存在液体泄漏行为。如检测到液体泄漏,立即反馈给后台人员及时处理。化工厂液体
    的头像 发表于 12-17 18:29 490次阅读
    化工厂液体<b class='flag-5'>泄漏</b>识别预警系统

    T3400系列制冷剂泄漏检测传感器:高效可靠的制冷监测方案

    在电子工程师的日常工作中,制冷系统的制冷剂泄漏检测是一个关键的设计领域。今天,我们深入了解一下Telaire的T3400系列制冷剂泄漏检测传感器,看看它有哪些独特之处。
    的头像 发表于 12-09 15:22 603次阅读
    T3400系列制冷剂<b class='flag-5'>泄漏</b>检测传感器:高效可靠的制冷监测方案

    便携气体探测器:地下燃气管网泄漏的“移动哨兵”

    城市地下燃气管网是城市能源输送的“地下生命线”,维系着千家万户的日常需求,但因其隐蔽性强、复杂性和环境干扰,泄漏风险始终存在。从施工事故导致的燃气爆燃,到设备老化引发的持续泄漏,每一次安全事件都在
    的头像 发表于 10-20 08:58 532次阅读
    便携气体探测器:地下燃气管网<b class='flag-5'>泄漏</b>的“移动哨兵”

    使用w5500通信使用wiz包的时候,突然拔掉网线,如何释放网络资源

    也就越多。也就是在拔掉网线之后调用closesocket并没有释放网络资源。这个时候再次接入网线,就无法继续通信了。需要重启w5500。但是重启w5500也无法解决内存泄漏的问题。 有没有人知道如何解决这个问题? 这个是我调用wiz_reset之后测试的效果
    发表于 10-11 09:01

    at_device 包 ml307长时间运行有内存泄漏问题怎么解决?

    使用 at_device 包中的 ml307 包长时间运行有大量内存泄漏问题,大概涨了20K,求助解决。
    发表于 09-24 07:41

    阀门总是微泄漏?气密性检测仪精准定位问题点-岳信仪器

    在工业生产的众多领域中,阀门是极为关键的部件,它掌控着流体的流动与停止,对整个生产流程的稳定运行起着至关重要的作用。然而,阀门微泄漏却是一个长期困扰着众多企业的难题。微小的泄漏不仅会造成资源的浪费
    的头像 发表于 09-20 11:32 435次阅读
    阀门总是微<b class='flag-5'>泄漏</b>?气密性检测仪精准定位问题点-岳信仪器

    打造私密安全空间,PicoScope3000D帮助您

    在现代办公室中,打造私密、安静的空间至关重要,无论是用于人力资源会议、心理健康支持,还是机密通话。但要确保有效的隔音措施却颇具挑战,尤其是当声音通过通风口、门框和窗户外泄时。在公司的一间指定人力资源
    的头像 发表于 09-12 17:23 1070次阅读
    打造私密安全空间,PicoScope3000D<b class='flag-5'>来</b>帮助您

    防爆气体泄漏红外成像仪LST360采用取景器(OLED)1280*1024像素!让隐形气体泄漏无处遁形

    减少了粉尘、二氧化硫等危险气体的出现,改善了空气的质量。但在使用的过程中,如果管道运输途中出现气体泄漏会导致生产生活的中断,造成资源的浪费,还会埋下安全隐患,这期
    的头像 发表于 08-26 17:08 934次阅读
    防爆气体<b class='flag-5'>泄漏</b>红外成像仪LST360采用取景器(OLED)1280*1024像素!让隐形气体<b class='flag-5'>泄漏</b>无处遁形

    如何通过PinView检查I/O电流泄漏

    如何通过PinView检查I/O电流泄漏
    发表于 08-25 07:45

    ArkUI-X资源分类与访问

    类型(type)和资源名称(name)引用。| 通过指定资源类型(type)和资源名称(name)引用。| 通过指定文件路径和文件名
    发表于 06-23 22:39

    在OpenVINO™ C++代码中启用 AddressSanitizer 时的内存泄漏怎么解决?

    在 OpenVINO™ C++代码中启用 AddressSanitizer 时遇到内存泄漏: \"#0 0xaaaab8558370 in operator new(unsigned
    发表于 06-23 07:16

    飒特红外热成像技术助力气体泄漏检测

    随着美国、欧洲率先立法,全球各国政府正紧跟其后,策划实施LDAR(Leak Detection and Repair,泄漏检测与修复)法规以遏制气体泄漏,主要针对石油炼化厂、化工厂的挥发性有机化合物(VOCs)及有害空气污染物(HAPs)。
    的头像 发表于 06-18 10:40 1451次阅读

    输电线路绝缘子泄漏电流监测装置:守护电网安全的“科技哨兵”

    在电网系统中,绝缘子作为支撑导线和防止电流回地的关键部件,其性能直接影响输电线路的安全运行。当绝缘子表面因污秽、潮湿或覆冰等因素导致泄漏电流增大时,可能引发污闪事故,造成大面积停电。为实时监测绝缘子状态,泄漏电流监测装置应运而生,成为电网运维的重要技术支撑。
    的头像 发表于 04-23 09:40 899次阅读