JVM 内存溢出排查

说明:记录一次JVM内存溢出的排查过程;

场景

项目开发完成后,首次提交到测试环境。测试、产品同事反馈页面先是操作响应慢,抛出超时异常,最后直接无法使用。查看日志后得知是内存溢出

在这里插入图片描述

重启服务后,我对前端主要的几个长RT接口,使用Arthas进行了trace

在这里插入图片描述

排查

Step1:SQL问题

锁定到了时间主要消耗在一次数据库操作,首先想到这段SQL是否有问题。

在这里插入图片描述

但我把SQL单独取出来,拼接参数执行,时长非常短,不应该啊。

在这里插入图片描述

Step2:拦截器

这期间,我做了很多尝试,看了很多JVM内存溢出的文章,但是基本没有帮助。于是,我换了一种思路,项目重启后,疯狂调用慢接口,然后使用Arthas的dashboard命令,查看是否有异常的进程,结果如下:

在这里插入图片描述

可以看到有进程被阻塞了,再使用thread id命令,查看该进程情况,如下:

在这里插入图片描述

从上往下看,找到自己项目中的代码,按图索骥,我找到项目中的下面这段代码。这段代码在拦截器类里,拦截器是对操作数据库拼接参数、封装结果集时进行拦截操作,该段代码是封装结果集时会执行的。

	Cipher cipher = Cipher.getInstance(algorithmName, getSingleInstance());

问题可能出现在操作数据库,拦截器操作返回结果集的这一步,我先对该方法进行追踪,如下:

在这里插入图片描述

很明显,问题出在这里,每条记录耗时大几百毫秒,十条记录就是大几秒;

Step3:单例对象

	Cipher cipher = Cipher.getInstance(algorithmName, getSingleInstance());

回过头来,再分析这行代码。该方法是jdk提供的,应该没啥问题,重点是参数列表中的第二个方法getSingleInstance(),该方法写在该类里,是成员方法,目的是创建单例对象作为参数。查看该成员方法,代码如下(已脱敏)

	private static synchronized SingleBean getSingleInstance() {
	    SingleBean single = null;
	    if(single == null){
	        single = new SingleBean();
	    }
	    return single;
	}

该代码看上去怪怪的,单例对象不应该这么创建。于是我将代码修改成如下,即单例创建模式之一的双重检查锁定:

	private static volatile SingleBean single = null;
	
	private ThisClass() {
	}
	
	/**
	 * 创建单例对象
	 */
	private static SingleBean getSingleInstance() {
	    if(single == null){
	        synchronized (ThisClass.class) {
	            if(single == null){
	                single = new SingleBean();
	            }
	        }
	    }
	    return single;
	}

修改完之后,再调用一次接口,结果如下:

在这里插入图片描述

Nice!就是这个单例对象创建的问题。

复盘

这个问题,前前后后花了一整天的时间,从早上搞到晚上,最终解决,简单复盘一下,分为代码问题,其他问题;

代码

	private static synchronized BouncyCastleProvider getSingleInstance() {
	    BouncyCastleProvider provider = null;
	    if(provider == null){
	        provider = new BouncyCastleProvider();
	    }
	    return provider;
	}

这段创建单例对象的代码,经分析可知:

  • static:导致了创建的对象不会被JVM回收;

  • synchronized:导致了线程的阻塞;

  • 错误的创建方式:导致每次查询都会创建大量的对象(每查一条记录就创建一个);

综合结果,就是JVM内存溢出,系统越用越慢,最终崩溃。

其他

其他原因来自两方面,场外因素和自身原因。

  • 场外因素:本身项目进度紧张,刚上测试,问题就提了一堆,而我们一个JVM溢出问题就搞了一天,产品同事也慌了,当天开了两次碰头面,又压缩了我们解决问题的时间。当时真有点“软件危机”的感觉。

  • 自身原因:排查思路开始有问题,因为页面上并不是所有接口都慢,大部分是正常的。所以我分析是两个问题,一个是慢接口,一个是导致系统崩溃的JVM内存溢出的问题,应该要优先解决后者。没想到这两个是同一个问题。另外,就是被java.lang.OutOfMemoryError唬住了,总感觉是非常不容易发现的问题,搞得我们还去找JVM的视图化工具,看JVM相关参数,除了知道溢出了毫无帮助。

另外

在解决问题过程中,学会了一些JVM相关的命令和工具,在这里Mark一下;

JVM视图工具

JDK自带视图化工具,如果你安装了JDK,可在CMD窗口敲下面的命令打开;

在这里插入图片描述

打开后,可查看Java进程相关的JVM参数,也支持远程连接,当然需要远程那边运行Java时配置相关参数,还需要主机可被访问;

在这里插入图片描述

JVM 内存泄漏排查

参考下面这篇文章,当时也敲了一些命令来排查问题。

  • Java诊断工具-Arthas保姆级教程

当时,我对测试环境项目敲了下图的代码,确实可以发现FGC频繁,且时长越来越长;

在这里插入图片描述

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

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

相关文章

接口测试实战教程(加密解密攻防)

🍅 视频学习:文末有免费的配套视频可观看 🍅 关注公众号【互联网杂货铺】,回复 1 ,免费获取软件测试全套资料,资料在手,涨薪更快 一、对称加密 对称加密算法是共享密钥加密算法,在加…

RuntimeError: Error compiling objects for extension虚拟环境和系统环境——添加、删除、修改环境变量

前言:因为一个报错RuntimeError: Error compiling objects for extension 没有配置cl.exe环境变量,我的应用场景是需要搞定虚拟环境变量配置 RuntimeError: Error compiling objects for extension手把手带你解决(超详细)-CSDN博…

Mybatis 之 useGeneratedKeys

数据库中主键基本都设置为自增,当我们要插入一条数据想要获取这条数据的 Id 时,就可使用 Mybatis 中的 useGeneratedKeys 属性。 背景 这里以 苍穹外卖 中的 新增菜品 功能为例,有 菜品表(dish table)和 口味表(dish_flavor table)&#xf…

HTML标签之有序列表,无序列表,自定义链表

无序列表 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…

从零开始学数据分析之数据分析概述

当今世界对信息技术的依赖程度在不断加深&#xff0c;每天都会有大量的数据产生&#xff0c;我们经常会感到数据越来越多&#xff0c;但是要从中发现有价值的信息却越来越难。 这里所说的信息&#xff0c;可以理解为对数据集处理之后的结果&#xff0c;是从数据集中提炼出的可用…

redis 高可用与 持久化

目录 一 redis 高可用 &#xff08;一&#xff09;redis高可用技术 1&#xff0c;持久化 2&#xff0c;主从复制 3&#xff0c;哨兵 4&#xff0c;Cluster集群 二 redis 持久化 &#xff08;一&#xff09;持久化相关概念介绍 1&#xff0c;持久化的功能 2&…

Pygame基础9-射击

简介 玩家用鼠标控制飞机&#xff08;白色方块&#xff09;移动&#xff0c;按下鼠标后&#xff0c;玩家所在位置出现子弹&#xff0c;子弹匀速向右飞行。 代码 没有什么新的东西&#xff0c;使用两个精灵类表示玩家和子弹。 有一个细节需要注意&#xff0c;当子弹飞出屏幕…

实战 | YOLOv8自定义数据集训练实现手势识别 (标注+训练+预测 保姆级教程--含数据集)

导 读 本文将手把手教你用YoloV8训练自己的数据集并实现手势识别。 安装环境 【1】安装torch, torchvision对应版本,这里先下载好,直接安装 pip install torch-1.13.1+cu116-cp38-cp38-win_amd64.whlpip install torchvision-0.14.1+cu116-cp38-cp38-win_amd64.whl 安装好…

剑指offer打卡 JZ7 重建二叉树

在牛客网刷的&#xff0c;还是跟leetcode一样非acm模式&#xff0c;由于急着暑期实习题量不固定&#xff0c;八股算法轮刷 打卡内容偏个人笔记&#xff0c;本人水平一般(代码随想录稀里糊涂刷了一遍)&#xff0c;从小白开始分析(甚至会分析语法)&#xff0c;尽量一题多解深入探…

VSCode好用插件

由于现在还是使用vue2&#xff0c;所以本文只记录vue2开发中好用的插件。 美化类插件不介绍了&#xff0c;那些貌似对生产力起不到什么大的帮助&#xff0c;纯粹的“唯心主义”罢了&#xff0c;但是如果你有兴趣的话可以查看上一篇博客&#xff1a;VSCode美化 1. vuter 简介&…

LabelConvert: 目标检测和图像分割数据集格式转换工具

LabelConvert LabelConvert是一个目标检测和图像分割的数据集格式转换工具&#xff0c;支持labelme、labelImg与YOLO、VOC和COCO 数据集格式之间的相互转换。 支持的转换格式 安装 pip install label_convert具体使用方法 由于文章篇幅所限&#xff0c;请移步LabelConvert官…

左值与右值,以及c++11的相关特性。

目录 左值 右值 左值引用总结&#xff1a; 右值引用总结&#xff1a; 右值引用使用场景和意义&#xff1a; 1、左值引用的使用场景&#xff1a; 编译器优化1&#xff1a; 2、移动构造与移动赋值&#xff1a; 3、右值引用的使用场景&#xff1a; 编译器优化2&#xff1a…

MATLAB科研绘图与学术图表绘制从入门到精通

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

软件资源分享六:EPLAN Electric P8 2024 | Eplan 2024 中文版软件介绍+保姆级安装教程

原文链接&#xff1a;安装激活教程 EPLAN Electric P8 2024 | Eplan 2024 中文版软件介绍安装教程 EPLAN 2024是一款电气设计软件&#xff0c;它可以用于自动化系统的设计、文档编制和维护。EPLAN可以对电气设计的各个方面进行完整的支持&#xff0c;包括电气控制系统、机械设…

新手学python还是c?

考虑到个人情况和职业规划是非常重要的。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在后台发给你。 Python作为初学者入门语言…

基于单片机温湿度PM2.5报警设置系统

**单片机设计介绍&#xff0c;基于单片机温湿度PM2.5报警设置系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机温湿度PM2.5报警设置系统概要主要涵盖了系统的整体设计思路、硬件组成、软件实现以及报警功能等关键方…

HCIP综合实验1

一.实验拓扑 二.实验要求 1、R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有Ip地址; 2、 R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff1b; R2与R5之间使用PPP的CHAP认证&#xff0c;R5为主认证方; R3与R5之间使用HDLC封装; 3、R2、R3…

高密度集成可伸缩无机薄膜晶体管

引言 与有机晶体管相比&#xff0c;无机半导体晶体管具有优越的性能和可靠性。然而&#xff0c;由于其脆性&#xff0c;不利于制造可拉伸的电子产品。由于这一缺点&#xff0c;它们大多被放置在不可拉伸的部件上&#xff0c;以避免机械应变&#xff0c;加重连接这些刚性部件的…

Java中的可变字符串

Java中的可变字符串 一、什么是可变字符串二、可变字符串的使用场景以及使用步骤1.新建一个可变字符串2.可变字符串的一系列方法 一、什么是可变字符串 可变字符串是Java.lang包下的 在我们学习到JDBC的时候需要将原有的sql语句根据不同的差异添加一段新的关键字或者单词&…

【C语言】函数(涉及生命周期与作用域)

文章目录 函数&#xff08;function&#xff09;**函数的概念****函数的作用**在本阶段一般会涉及到两类函数:库函数和自定义函数自定义函数**函数的语法形式** **形参和实参****实参和形参的关系** 函数返回值**函数返回值类型说明****return 语句** 数组做函数参数**函数嵌套…