[转帖]JVM OOM内存溢出分析实战(基于MAT工具)

news/发布时间2024/8/25 9:56:29
https://juejin.cn/post/7342679747636215858?searchId=202404070705500138968B5F69BF68EA87

 

前言

  在Java开发与运维过程中,JVM内存管理扮演着至关重要的角色,尤其在面临高性能、大数据量处理的场景时,如何有效防止和解决JVM堆OOM问题显得尤为关键。

  最近写了一个涉及海量数据计算的功能,在线上发生了OOM,本文介绍了基于MAT工具分析堆内存溢出的过程。

知识储备

  阅读本文需要对JVM内存模型和GC有一定的知识储备,对Spring事务管理和Mybatis有一定的了解。

1. MAT工具的下载和安装

1.1 下载

选择自己需要的版本,我本次使用的是Windows版本:官网下载地址 图片.png

1.2 安装

解压即可,获得以下目录

图片.png

MemoryAnalyzer.exe 为启动文件,双击启动即可

2. JVM内存快照—dump文件的生成

线上的做法是添加JVM参数,以便在发生OOM时生成内存快照。

 
shell
复制代码
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=E:\AppData\Mat\kylin2.hprof

也可以使用jmap手动dump

 
shell
复制代码
jmap -dump:live,format=b,file=<filename.hprof> <pid>

3. 实战分析

3.1 快照导入MAT

图片.png 图片.png

在这里插入图片描述

选择 Open Heap Dump,打开快照文件,会得到一个预览面板

3.2 内存分析

图片.png

点击详情后其实我们可以获得很多直观而且关键的信息了

3.2.1 初步分析

图片.png 图片.png 图片.png 图片.png 图片.png 图片.png

  1. 黄色区域大概意思是主线程占用了99.17%的内存,内存集中在一个HashMap中并占用了96.47%;
  2. 查看 Shortest Paths To the Accumulation Point ,我们发现了java.util.HashMap是被一个 org.apache.ibatis.cache.impl.PerpetualCache引用了,这个类是嘛呢,有经验的同学其实可以推断出来了,是与mybatis缓存相关的类,继续往下看;
  3. 查看 Accumulated Objects in Dominator Tree ,这是一个引用链,也可以很直观的看到主线程中有一个 org.apache.ibatis.cache.impl.PerpetualCache 引用了大量的java.util.HashMapPerpetualCache的内部实现就是HashMap,只是现在我们还不知道HashMap中存了什么,先继续往下看;
  4. 我们直接看 All Accumulated Objects by Class,com.nes.kylin.powerstation.domain.clickhouse.bo.DeviceBranchHistoryData 首当其冲,基本可以确定是它的问题了,那如何验证我们的猜想呢?

3.2.2 深入分析

回到预览面板,点击 Histogram,查看类维度的分析

图片.png 图片.png

这里我们又看到了 com.nes.kylin.powerstation.domain.clickhouse.bo.DeviceBranchHistoryData

图片.png

单击 with incoming references 查看该类的实例

图片.png

这里得到的是内存中该类的实例列表,我们随意找一个对象,继续单击 with incoming references 查看该对象被谁引用了

图片.png

得到如图,我们将对象信息展开,再一次见到了 org.apache.ibatis.cache.impl.PerpetualCache,这个类mybatis的一级缓存类,接下来我们review代码,去分析和解决问题,初步结论是mybatis中的缓存没有及时释放。

图片.png

再结合程序运行时趋势递增的内存变化曲线,基本可以确定有大量的对象没能及时释放内存,造成了堆积,最后发生OOM。

4. 结论

4.1 代码分析

 
java
复制代码
解释
 
 
for (String targetStationCode : targetStationCodes) {
    shadowRecognitionBizService.forecastByStation(targetStationCode, dataTime, stationCleanInfoMap.get(targetStationCode), randomForestInstancesPair, deleteTag, algoPartitionDays);
    
    ...
    
}
 
java
复制代码
解释
 
 
@Transactional(rollbackFor = Exception.class)
public void forecastByStation(String stationCode, Date dataTime, Date cleanDate,
                              Pair<RandomForest, Instances> randomForestInstancesPair,
                              int deleteTag, int algoPartitionDays) throws ParseException {

    ...

}
 
xml
复制代码
解释
 
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nes.kylin.powerstation.domain.clickhouse.dao.ClickhouseDeviceMapper">

    ...
    
    <select id="selectBranchData" resultType="com.nes.kylin.powerstation.domain.clickhouse.bo.DeviceBranchHistoryData">
        SELECT
        toUnixTimestamp(ts,'Asia/Shanghai') AS dateTs,
        ts AS date,
        sn AS sn,
        ${pointBranch}
        FROM ${tableName}
        where qos = 1
        and sn in
        <foreach collection="sns" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
        and ts >= #{startTime} and ts &lt;= #{endTime}
        order by ts
    </select>
    
    ...

</mapper>

这里循环 targetStationCodes,在 shadowRecognitionBizService.forecastByStation() 方法中声明了事务,并且有通过 mybatis 分批次查询较大数量级数据的操作。我们基本可以断定是 selectBranchData 这个查询返回的 DeviceBranchHistoryData 在内存中占用的空间没能释放,造成了堆积。

4.2 结论

  结合之前的分析,DeviceBranchHistoryData的实例是被PerpetualCache引用的,那问题的根源就是PerpetualCache了。

  熟悉mybatis的同学知道,PerpetualCache 是mybatis一级缓存的类(这里不对mybatis做展开分析)。mybatis一级缓存的生命周期是依赖于SqlSession,SqlSession关闭了,一级缓存也会被清空。那为什么没能及时释放呢?因为在Spring环境中,一个 @Transactional 下使用的SqlSession是同一个,即事务没结束,SqlSession没close,缓存没能释放,造成了对象堆积,引发了OOM。

  在我的场景中,我选择保证原有代码逻辑,关闭这个sql的一级缓存,即在select标签中添加 flushCache="true"

5. 总结

  综上,本文通过实际案例结合MAT工具,分析和解决了突发的JVM内存溢出问题。在实际应用中,会有更加复杂多变的情况,要结合实际的情况去分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.liansuoyi.cn/news/31380843.html

如若内容造成侵权/违法违规/事实不符,请联系连锁易网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

解决虚拟网卡无法连接到 Internet 问题(之一)

虚拟网卡无法连接到 Internet 的可能情况之一是:网络连接中存在不支持网络连接共享(ICS)的网络连接,可以在 "控制面板\网络和 Internet\网络连接" 中查看是否存在不支持 ICS 的网络连接。 我遇到的情况是我电脑中存在一个名为 “传入的连接” 的网络连接,我不知…

【安全服务系列】-- 勒索病毒处置流程

二、 勒索病毒的应急响应(三)断网隔离被感染的机器,进行以下排查工作:

4 7

使用阿里云服务服务的步骤: 阿里云控制台首页 (aliyun.com) OSS管理控制台 (aliyun.com) RAM 访问控制 (aliyun.com) 密钥是要创建时显示,然后就不在显示在springboot集成redis,会自动向ioc容器中注入对象

SQLAlchemy详解

一、SQLAlchemy介绍SQLAlchemy 是 Python SQL 工具包和对象关系映射器,为应用程序开发人员提供 SQL 的全部功能和灵活性。SQLAlchemy支持SQLite、PostgreSQL、Oracle、MySQL、MariaDB、Microsoft SQL Server等多种数据库。 二、SQLAlchemy安装我安装的版本是:SQLAlchemy==2.0…

2024最新AIGC系统ChatGPT网站源码,GPTs应用,Ai绘画网站源码

SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型+国内AI全模型。本期针对源码系统整体测试下来非常完美,那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧。已支持GPT语音对话、GPT-4模型、DALL-E3文生图、图片…

吴恩达机器学习-第一周

吴恩达机器学习-第一周 学习视频参考b站:吴恩达机器学习 本文是参照视频学习的随手笔记,便于后续回顾。 机器学习定义 Field of study that gives computers the ability to learn without being explicitly programmed.--Arthur Samuel(1959) 编译了跳棋程序,程序自己下棋迭…

注意力机制 transformer

https://jalammar.github.io/illustrated-transformer/ X就是输入的向量 ,第一步就是创建三个输入向量qkv第二步是计算分数:分数决定了对输入句子的其他部分的关注程度。 分数是通过查询向量与我们要评分的各个单词的键向量的点积来计算的。因此,如果我们处理位置#1中单词的…

nginx反向代理实现不同域名映射到同一台服务器的相同端口

在实际应用中,我们经常会遇到多个域名需要映射到同一台服务器的相同端口的情况,这时可以使用nginx反向代理来实现。 以实现将www.example.com和www.test.com都映射到127.0.0.1的80端口为例,具体步骤如下:修改hosts文件在本地hosts文件中添加以下两行: 127.0.0.1 www.examp…

Photoshop混合模式的底层原理

Photoshop虽然不是什么高手,但平时工作中难免会用到,处理部分需求还是可以胜任的。接触PS这么多年,对PS中图层的混合模式(Blend Mode)一直就处于懵懂状态,即使是看了教材及视频后,有了一点感性认识,但在实际操作中仍旧无法运用起来。直至某一天,我在B站看到韩世麟的《把…

go~在阿里mse上使用redis.call

相关依赖github.com/higress-group/proxy-wasm-go-sdk github.com/alibaba/higress/plugins/wasm-go标准的redis 下面是一个读取redis指定key的方法,使用了higress的wasm-go组件实现的err := config.Client.SMembers("online", func(response resp.Value) {for _, i…

v-show和v-if的区别

v-show可以写在dom标签中,可以根据表达式的true还是false来判断是否显示该标签的内容 v-show是通过css属性的display来控制是否显示的,不删除元素 v-show: 在所写的代码中按住f12选择样式,display被划掉了,元素被显示了 当display勾选的时候,元素不显示了 所以v-show更适…

中文GPTS详尽教程,字节扣子Coze插件使用全输出

今天,斜杠君和大家分享如何在字节扣子Coze中创建插件,并在创建后如何使用这个插件。一、新建插件 首先,进入到插件页面,创建一个插件。 https://www.coze.cn/home点击左侧的个人空间。 在上面选择”插件“标签,来到插件的页面。点击”创建插件“按钮,开始创建。在弹出的…

Adobe Media Encoder 2024 v24.3 (macOS, Windows) - 格式转换

Adobe Media Encoder 2024 v24.3 (macOS, Windows) - 格式转换Adobe Media Encoder 2024 v24.3 (macOS, Windows) - 格式转换 Acrobat、After Effects、Animate、Audition、Bridge、Character Animator、Dimension、Dreamweaver、Illustrator、InCopy、InDesign、Lightroom C…

最会的一集

用完我的风扇终于不吵了。

CPU、内存占用高,其实是因为系统防护的一个运行程序MsMpEng.exe,在任务管理器中叫做Antimalware service executable,中文意思为反恶意软件服务可执行文件,主要的作用是监视计算机中是否存在潜在威胁,并提供实时保护,来防止恶意软件和网络攻击,但是在运行的过程中会大量…

Ubuntu ufw 命令

Ubuntu 22.04 自带ufw 无需下载 ufw是Uncomplicated Firewall的缩写,是一个用户友好的命令行工具,用于管理Ubuntu系统上的防火墙。通过ufw命令,用户可以轻松地配置防火墙规则、查看当前的防火墙状态、启用或禁用防火墙等操作,帮助用户保护系统安全并控制网络流量。查看防火…

Camera KMD ISP学习笔记(3)-component应用

学习资料:https://deepinout.com/camx-kmd/camera-kmd-camsync-v4l2-driver-model-intro.html 仅用于个人学习,侵联删 KMD Camera ISP子系统入口接口及文件 驱动文件入口:drivers/camera_init.c 整个camera KMD驱动的入口接口:module_init(camera_init);重要数据结构:str…

2-37. 代码链接 UI 实现时间日期对应转换

创建 TimeUI初始化,并注册事件修改 EventHandlerTimeManager 来唤起事件增加作弊代码按 T 的时候快速跳过一分钟 项目相关代码 代码仓库:https://gitee.com/nbda1121440/farm-tutorial.git 标签:20240405_2104

(待完善)ping不通物理机

问题的关键点:物理机ipv4与虚拟机ipv4相同解决方法: 更改虚拟机静态ipv4,更改映射点击查看代码 [root@hadoop101 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-p…

免版权素材库:在营销和宣传中的重要性与应用

免版权素材库在宣传和营销中的重要性不言而喻。在当今数字化时代,图片、视频、音频等多媒体素材在营销和宣传中扮演着至关重要的角色。然而,获取高质量的素材并避免版权问题一直是许多企业和个人面临的挑战。免版权素材库的出现为用户提供了一个便捷、安全且经济高效的解决方…
推荐文章