记一次生产环境Java堆内存溢出问题排查思路

文章目录

  • 1. 用Visual VM 加载堆转储文件
  • 2. 用Visual VM 分析堆转储文件
  • 3. 结合分析结果,定位并解决问题

1. 用Visual VM 加载堆转储文件

先将转储文件从服务器下载下来,打开Visual VM,点击右上角的Load Snapshot,将这个转储文件加载到Visual VM中。
在这里插入图片描述

2. 用Visual VM 分析堆转储文件

1)首先看到是醒目的红色,这里标记了堆内存溢出的线程,我这里显示是Nacos的配置中心的一个更新本地配置的Updater线程导致堆内存溢出。
我本地debug发现,这个线程里边根本就不会创建太多对象。而且本地测试环境的配置文件数 、配置文件内容大小不会与生产环境相差太多,那么可以推测生产环境也不会创建太多的对象。因此可以进一步推测不是这个线程导致的内存溢出。实际情况可能是在此之前就已经内存不足了,只是在这个线程任务中GC已经不起作用了、实在是分配不了新对象,最终程序崩溃。

在这里插入图片描述
2)不能直接从线程上看出问题所在,就只能去看java对象的分布情况了。

Class by Number of InstancesClasses by Size of Instances两个维度都可以看出byte[]char[]String 的对象个数及内存大小都是排在最前列的。
光看这几种对象其实没啥意义,因为它们是最常见的几种准标量,它们几乎在任何系统的任何时候都是数量最多、内存占用最大的,它们一般都是被其他复杂对象给引用着,所以我们主要还是得关注这些复杂对象
除了这个常见的准标量外,可以直观看到EnterpriseProjectDO 对象占用内存最大。看到这个Java类型的对象很多,我第一反应就是我负责的那个定时任务可能在运行,那个定时任务会创建大量的EnterpriseProjectDO对象。但后来又细想了下,白天那个定时任务不会运行,它的执行计划是每晚11点,后来在XxlJob的用户界面复查发现当时也没有其他人手动执行那个定时任务。

我只能扩大排查范围,后来在Dominators By Retain Size维度看到了关键信息
在这里插入图片描述
点击Dominators By Retain Sizeview all按钮显示出一下结果
在这里插入图片描述
从上图可以看出,用绿框标注出的对象是重点怀疑对象,这几类对象数量多、占用内存大,且有好几个还是GC Root。

  • (1) 先看排第一的ResultSetImpl,这说明此时数据库查询向java程序返回了很大的数据报文。
  • (2) 再看ArrayList#115426这个对象,其中的元素类型是EnterpriseMainAndCredential,因此需要关注某个代码逻辑会用到这个类。
    在这里插入图片描述
  • (3) 然后看HashMap#26865这个对象,展开后发现,这个HashMap的key是Long类型、value是ArrayList(其元素类型是EnterpriseCredentialDO),这明显是一个Java 8 对集合进行stream分组的结果。因此得重点排查对项目中对EnterpriseCredentialDO的分组代码
    在这里插入图片描述
  • (4) 再然后看ConcurrentHashMap#239这个对象,展开这个map发现,它的key是Bean名、value是Bean对象,可以推测出这个对象是DefaultListableBeanFactory中记录bean名到bean实例之间映射的字段singletonObjects ,因此这个对象对我们排查问题没啥参考意义。
    在这里插入图片描述
  • (5) 最后看ArrayList$SubList#1这个对象,展开这个对象后发现它是元素类型EnterpriseMainDOArrayList 的子视图,这个java项目中有使用内存分页,所以需要注意项目中对EnterpriseMainDO 集合调用subList进行分页的代码逻辑
    在这里插入图片描述

3. 结合分析结果,定位并解决问题

(1) 直接IDEA中搜索 EnterpriseMainAndCredential被引用的地方,很快就定位了一个代码位置,这个类只有那一个处被使用。这个接口没有传租户id,会导致查询所有的EnterpriseProjectDO,在这个接口中这个实体对应的数据库表的数据量是最大的,达到了30多万,反序列化为Java实体时会创建大量对象。

(2) 另外由于过滤条件复杂,主数据没法在数据库层做过滤,需要将所有的EnterpriseMainDO(数据量不大,总量才3000多条)查出,再做内存分页,所以在堆转储文件分析看到了元素类型是EnterpriseMainDOArrayList$SubList

(3) 代码中对EnterpriseCredentialDO EnterpriseProjectDO 都进行了stream 分组,所以在堆转储文件分析看到了上面提的的HashMap#26865对象。

(4) 内存溢出的原因也在于这里的stream 分组统计,代码中对这两对象集合分组后,只取了分组后的size,并未使用集合里的对象具体信息。EnterpriseProjectDO 的数据量特别大,且代码逻辑又只需要统计的count数,所以这个统计应该放在数据库上(利用group by统计)

(5) 最后,我改写了代码,用sql在数据库上做数据统计,大大减少了数据库的返回数据报文大小,java程序客户端也就不需要创建那么多的java数据库实体类,不会出现GC失败、内存溢出的问题了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑,这些问题可能会影响我们的开发效率和代码质量,因此我们需要不断总结和学习,以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结,以提高大家的开发质量。本系列文章…

外卖点餐APP开发需要哪些功能

uni-app框架:使用Vue.js开发跨平台应用的前端框架,编写一套代码,可编译到Android、小程序等平台。 框架支持:springboot/Ssm/thinkphp/django/flask/express均支持 前端开发:vue.js 可选语言:pythonjavanode.jsphp均支持 运行软件…

LeetCode_101(对称二叉树)

1.递归 public boolean isSymmetric(TreeNode root) {if(root null){return true;}return deepCheck(root.left,root.right);}boolean deepCheck(TreeNode left, TreeNode right){//递归的终止条件是两个节点都为空//或者两个节点中有一个为空//或者两个节点的值不相等if(lef…

RocketMQ 事件驱动:云时代的事件驱动有啥不同?

作者:林清山(隆基) 前言: 从初代开源消息队列崛起,到 PC 互联网、移动互联网爆发式发展,再到如今 IoT、云计算、云原生引领了新的技术趋势,消息中间件的发展已经走过了 30 多个年头。 目前&a…

如何应对MySQL单表数据量过大:垂直分表与水平分表策略解析

话接上回,单表最大数据建议两千万,那如果开发一个项目,预计注册量达到一个亿怎么办。 单表内放这么多数据,MYSQL底层B树的层级结构就可能会变得很高,磁盘io次数变多,性能会大幅度降低。所以考虑数据库分表…

01-Git 之快速入门操作本地仓库

https://learngitbranching.js.org/?localezh_CN在线练习git 1. Git 安装好Git以后, 先检查是否已经绑定了用户名和邮箱 git config --list1.1 为什么要使用版本控制? 从个人角度: 在做项目时,如果一点点去改代码会很乱,不利…

顺序表(C语言版)

前言:本篇文章我们来详细的讲解一下顺序的有关知识,这篇文章中博主会以C语言的方式实现顺序表。以及用顺序表去实现通讯录的代码操作。 目录 一.顺序表的概念 二.顺序表的分类 1.静态顺序表 三.动态顺序表的实现 1.顺序表的初始化 2.顺序表的尾插…

python 重载内置函数吗

python中是不支持函数重载的,但在python3中提供了这么一个装饰器functools.singledispatch,它叫做单分派泛函数,可以通过它来完成python中函数的重载,让同一个函数支持不同的函数类型,它提供的目的也正是为了解决函数重…

智能物联网远传冷水表管理系统

智能物联网远传冷水表管理系统是一种基于物联网技术的先进系统,旨在实现对冷水表的远程监测、数据传输和智能化管理。本文将从系统特点、构成以及带来的效益三个方面展开介绍。 系统特点 1.远程监测:系统可以实现对冷水表数据的远程监测,无…

累积分布函数图(CDF)的介绍、matlab的CDF图绘制方法(附源代码)

在对比如下两个误差的时候,怎么直观地分辨出来谁的误差更低一点?: 通过这种误差时序图往往不容易看出来。 但是如果使用CDF图像,以误差绝对值作为横轴,以横轴所示误差对应的累积概率为纵轴,绘制曲线图&am…

Python开源工具库使用之词云Wordcloud

文章目录 前言一、基本使用1.1 文本生成词云1.2 配置项 二、进阶用法2.1 自定义形状2.2 自定义着色2.3 自定义词频2.4 中文 三、实际案例3.1 工作报告词云3.2 周杰伦歌词词云 四、总结4.1 优点和局限性4.2 展望未来发展 参考 前言 当我们需要将大量文本数据可视化展示时&#…

不得不学的Zabbix监控系统,最细搭建详解

目录 一、为什么要做监控 二、Zabbix介绍 三、zabbix组成 四、Zabbix主要功能 五、zabbix 监控原理 六、zabbix运行机制 七、Zabbix的监控方式 7.1 主动模式 7.2 被动模式 八、Zabbix监控系统监控对象 九、Zabbix的优缺点 9.1Zabbix的优点 9.2Zabbix的缺点 9.3za…

ELK日志分析系统之Zookeeper

一、Zookeeper简介 ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:分布式锁服务。分布式应用可以基于它实现更高级的服务,实现诸如同步服务、配置维护和集群管理或者命名的服务。 Zookeepe…

腾讯云服务器CVM标准型S8实例CPU内存、网络和存储性能测评

腾讯云第八代云服务器标准型S8实例基于全新优化虚拟化平台,CPU采用Intel Emerald Rapids 全新处理器,睿频3.0GHz,内存采用最新DDR5,默认网络优化,最高内网收发能力达4500万pps,最高内网带宽可支持120Gbps。…

61、ARM/串口通信相关学习20240415

一、串口通信:实现PC端串口助手与开发板的字符串通信。 代码: main: #include "uart4.h"int main(){uart4_config();//char a;char s[64];while (1){//a getchar();//putchar(a1);gets(s);puts(s);}return 0;}usrt4.c&#xff…

protobuf 编码原理

简介 Protocol Buffers(protobuf),它是 Google 开发的一种数据序列化协议(与 XML、JSON 类似)。 优点: 效率高:Protobuf 以二进制格式存储数据,比如 XML 和 JSON 等文本格式更紧凑…

【虚幻引擎】DTProjectSettings 蓝图获取基本项目配置插件使用说明 获取项目命名,项目版本,公司名,公司识别名,主页,联系方式

本插件可以使用蓝图获取到项目的一些基本配置,如获取:公司名、公司识别名、版权声明、描述、主页、许可条款、隐私政策、项目ID、项目命名、项目版本、支持联系方式、项目显示标题、项目调试标题信息、应保留窗口宽高比、使用无边框窗口、以VR启动、允许…

CommunityToolkit.Mvvm笔记---Ioc

使用MVVM模式提高应用程序代码库中的模块化程度的最常用模式是使用某种形式的反转控制(Ioc)。其中最常见的解决方案是使用依赖关系注入,该解决方案存在于创建多个注入后端类的服务(即以参数的形式传递给 viewmodel 构造函数&#…

携程景点详情API:电商发展新引擎,推动旅游智能化升级

随着信息技术的快速发展,旅游行业正迎来一场深刻的智能化升级。作为电商发展的新引擎,携程景点详情API以其丰富的数据资源和高效的服务能力,正逐渐成为推动旅游智能化升级的重要力量。本文将深入探讨携程景点详情API在电商发展中的作用&#…

xhci 数据结构

xhci 数据结构 xhci 数据结构主要在手册上有详细的定义,本文根据手册进行归纳总结: 重点关注的包括: device contexttrb ringtrb device context设备上下文 设备上下文数据结构由xHC管理,用于向系统软件报告设备配置和状态信息。…