java.lang.OutOfMemoryError: Java heap space 案例分析

一、背景
  • 数据表导出excel时,数据量大于65w行,excel分为多个文件;测试导出200w数据出现内存溢出(java.lang.OutOfMemoryError: Java heap space),导致rcapi服务直接崩溃重启
二、目标
  • 让数据表200w数据可以顺利导出
三、引发的思考
  • 导出的逻辑挺复杂的,到底是哪块代码出现了问题,想着debug来排查,但是debug过程中,发现有很多地方的代码用时都挺长的,不好定位
  • 堆空间不足,是不是有哪里的代码不够规范,导致该释放的对象,一直没有被释放掉,debug过程中,对象太多了,还是不好判断
  • 对于内存占用这个地方只靠debug来看的话,不好判断,就想着JVM调优,别人是如何排查?之前只是听说过,没有实践过,理论也只会一丢丢
  • 百度发现jconsole命令有一个图形化界面可以帮助看堆变化情况,但是这个只观察到了变化,但是具体哪个对象引起的,哪地方的代码引起的还是不清楚
  • 又去查资料,发现jvisualvm命令可以打开一个图形化界面,这个界面比较友好,可以看到对象的实例化占用空间情况,这样就可以看看哪些对象占用了很多的空间
  • 又想知道是哪个地方的代码引起的,百度了一下,都是linux上的命令,本地不好使用,这时候找到了阿里巴巴一个工具arthas,通过这个工具可以观察到占用cpu过高的线程,然后可以看到线程的堆栈信息
  • 经过以上的过程,下边主要使用了ideadebug功能,jvisualvm观察内存变化和对象实例情况,然后通过arthas来观察线程的堆栈信息
四、排查过程:
1.启动rcapi服务,设置启动参数-Xms256m -Xmx8192m,然后运行程序

在这里插入图片描述

2.postman请求
  • 请求url:http://localhost:5002/rcapi/v1/xxxx/queryAndExportExcel
  • 请求参数:(省略)
  • 请求头:x-sso-fullticketid:xxxxxxxx
3.使用java VisualVM工具(主要用来观察堆变化和实例数)

输入jvisualvm,回车

4.使用阿里巴巴工具arthas(主要用来查看占用cpu的比较高的线程堆栈信息)
#打开浏览器,输入地址,下载arhas,放入指定目录
https://arthas.aliyun.com/arthas-boot.jar
#打开powershell 运行arhas
java -jar arthas-boot.jar

在这里插入图片描述
在这里插入图片描述

5.postman进行请求,查看堆内存的变化和实例数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6.当堆内存不断上升的时候,使用arthas查看线程占用cpu最高是哪个,以及对应的堆栈信息

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.结论:根据堆空间的变化,可以得出最高峰为7.5G左右;根据实例的变化,可以得出excel导出过程中产生了大量的Xobj$ElementXobjXobj$AttrXobj对象占用了空间
8.根据步骤67中得信息,进行debug调试
  • 全局搜索ElementXobjAttrXobj打上断点,观察什么时候,创建这些对象
  • 根据步骤6中的堆栈信息,作为思路排查
9.根据调试结果,可以得出创建excel内的一个小单元格内容,会产生一个Cell对象,setCellValue()setCellStyle()过程中产生的大量的Xobj$ElementXobjXobj$AttrXobj对象,只有sheet节点转化为流之后,对象才会被释放掉
五、处理方案
  • 1.三种思路

    • 调整堆内存,调整线上jvm参数-Xmx8192m
    • 修改导出限制,65w修改为20w
    • 调整基础导出类
  • 2.选择 修改导出限制,65w修改为20w,并且把启动参数修改为-Xms256m -Xmx4096m(已在dev3环境进行线上测试过,可以导出成功)
    在这里插入图片描述


附录:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中的"java.lang.OutOfMemoryError: Java heap space"错误表示Java堆空间不足。这通常发生在程序需要分配更多内存给对象,但Java堆空间已经用尽的情况下。这个错误通常是由以下原因引起的: 1. 内存泄漏:程序中存在内存泄漏,即创建的对象没有被正确释放,导致堆空间被占满。 2. 大对象:程序中创建了过多的大对象,导致堆空间不足。 3. 堆空间设置不合理:Java堆空间的大小没有根据程序的需求进行适当的调整。 解决"java.lang.OutOfMemoryError: Java heap space"错误的方法有以下几种: 1. 增加堆空间大小:可以通过修改JVM的启动参数来增加堆空间的大小。例如,可以使用"-Xmx"参数来增加最大堆空间的大小,使用"-Xms"参数来增加初始堆空间的大小。例如: ```shell java -Xmx2g -Xms1g YourProgram ``` 这将将最大堆空间设置为2GB,初始堆空间设置为1GB。 2. 优化代码:检查代码中是否存在内存泄漏的问题,并确保及时释放不再使用的对象。可以使用Java的垃圾回收机制来自动释放不再使用的对象。 3. 减少对象的创建:尽量避免创建过多的大对象,可以考虑使用对象池或者缓存来重复利用对象,减少对象的创建和销毁次数。 4. 使用更高效的数据结构:如果程序中使用了大量的集合对象,可以考虑使用更高效的数据结构,例如HashMap代替Hashtable,ArrayList代替Vector等。 5. 分析内存使用情况:使用Java的内存分析工具,如VisualVM、jmap等,来分析程序的内存使用情况,找出内存占用较大的对象和代码段,并进行优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值