IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 记一次Java heap space生产问题排查 -> 正文阅读

[大数据]记一次Java heap space生产问题排查

阳光明媚的下午,突然甲方打电话过来说系统用不了,验证码一直加载不出来,登陆不了系统了。然后开始bibibi,你们怎么回事啊,赶快排查恢复并且交给我们一份故障检查报告。当时就心态就崩了,打开电脑登陆VPN连接到远程服务器上开始排查问题。

问题排查

连上服务器后,第一反应检查redis集群是不是有问题,登陆redis服务器的一台节点,查看cluster info和cluster nodes发现redis并无异常。因为验证码这玩意是存在redis的,所以第一反应就是看redis是不是有问题。

redis正常,那么就去看web服务器的web-error.log日志,惊呆了,java.lang.OutOfMemoryError: Java heap space,这时候我就已经确定了,我们JVM的堆空间不足导致内存溢出的问题。

dump日志的获取

此处有个小提示,在部署这种系统的时候都是需要加上一些必要的jvm参数的,比如我在部署这台web的时候就增加了:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/jvmdump,所以遇到这个问题我并不是太担心,进入目录/opt/jvmdump看到java_pid27548.hprof文件,大小在1.12G,还是挺大的,这个文件会挺大的,相当于当时的内存使用大小,不必惊讶。

我将java_pid27548.hprof文件进行压缩,传输回本地,然后就将开启我的排查之路。

开始排查

首先我们倒入hprof文件到VisualVM,可以看到分为6个区域。

1区域是堆信息展示,堆大约是1G,还有类、实例等一些信息。

2区域是服务器上的一些参数信息。

3区域是按实例数划分的类,最大的是BigDecimal其次是char[],以及string等等,以及分别占用了总实例数的百分比。char的实例数达到了5001143占总数量的24.5%。我们在一区域看到instances为20402517,用计算器核查了一下,确实是这样。

4区域是按实例大小划分的类,也是由大到小依次排序,单位是B,BigDecimal占用的大小为336979536B,大概就是337M,占总堆的34.1%,我们的总Size为987908640B,除一下为0.3411也就是34.1%。

漏掉了一个很重要的区域,就是1区域和3区域中间的标题为:OutOfMemoryError Thread,内存溢出线程区域。这个区域的提示就是告诉我们造成这次堆空间溢出的线程是哪个,所以我们的重点就在这个地方。

在这里插入图片描述

首先我们看到这些信息时,是不是一脸懵逼,我们可以点开4区域,查看到这一个很大的BigDecimal对象,但是这些东西怎么定位到我的代码???,怎么看是哪里导致的大对象呢???这里展示的内容只是一些凌乱的单个对象的信息,和我们的Service,Controller等关联不到一起。显然这里是无法排查出问题的。

在这里插入图片描述

通过上面的图我们可以很清楚的知道是因为一些对象占用太多空间,导致的堆溢出异常,所以后续就是需要定位那些地方会产生较大的对象,所以我们回到OutOfMemoryError Thread[view all]区域,点击view all找到标红的异常线程信息。

通常由于代码编写的不够严谨,在使用List或者Map对象的时候塞入了很多值,然后再内存中进行各种处理的时候会出现堆过大的问题,因为大对象是直接到老年代的。或者我们查询了一个时间跨度很大的数据,几十万条这种导致返回的集合过大。

说这么多就是为了告诉你,我们看这个区域内的线程信息时,找自己写的类的全限定路径,比如我们的com.qhyu.cloud.****Service;类似这种我们自己项目的路径信息。

在这里插入图片描述

我是从下往上慢慢开始找,很快我就找到了这个项目内的类名,毕竟保密协议,所以打了马塞克。这些类似超链接一样的蓝色的链接都是可以点的,可以查看运行时的状况。从下往上我依次找到了相关的controller,service,dao等信息,我点了一个最上面的NativeQueryImpl#1的链接。

在这里插入图片描述

点进去发现其实是这个线程是在查询一次数据库,绑定的参数很明显只有两个startTime和endTime,区间在2021-07-01到2021-07-31。然而这并不是我想要的,继续回到Threads模块往上找。

在这里插入图片描述

然后我就找到了一个ArrayList,我想看看这个查询出来的对象有多大,所以直接点进去看看详情。

在这里插入图片描述

我们点击Fields查看元素,发现elementData是个大对象,size大小有374567,里面全是String和BigDecimal,这时候我反应过来了,刚刚4区域的信息都是因为这个返回造成的。也就是说导致我们生产上出现假死的就是这个线程查询的时候返回的对象太大,当线程还没有结束的时候其他线程想要分配堆空间的时候,执行full gc也还是没有回收,一段时间后就报异常了。

在这里插入图片描述

当然这个问题是由于我们的某些大表数据量在千万级别,查询一个月的数据也在几十万数据量,只是这个朋友在写代码的时候没有调用分页的dao层方法,导致这个模块在使用的时候出现了问题,所以还是得细心呀,码农也得有自己的职业操守不是。

Java核心编程

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:36:52  更:2021-09-04 17:37:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:59:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码