记一次内存溢出问题的排查、分析过程及解决思路
谨以此文献给自学路上的兄
起因
这个测试工具的开发已有一段时间了,由于数据量过大,写入数据较慢,导致工具执行耗时较长,所以再次优化了实现方案,进行二阶段的程序开发。
经优化后,2000 条数据写入,耗时4秒,个人感觉,快了很多了。
于是,想知道批量执行需要耗时多久。
结果10分钟、20分钟、1 个小时过去了...
程序一直在写入数据,等的我这个蓝瘦呀,寻思去泡杯茶吧。
结果,接完水回来,尼玛报错了,如下图所示:
心里过程
虽然,作为一个测试喵,编码能力与纯开发相比,根本不是一个层次的。
当然,也可以通过求助开发同事解决,但这并不是退缩、逃避解决问题的理由。
这个报错,我也是第一次遇到,对于一个不了解内存问题的测试来说,无疑是艰难的,结果各种搜。
最后,定位到是内存溢出导致的。
说实话,这个报错卡了我近1.5天,几次想找同事解决,但还是忍住了,还是想尝试自己努力去解决。
常见的几种内存溢出
- Java heap space
- GC overhead limit exceeded
- PermGen space
- Metaspace
尝试过程
小编经验有限,目前只遇到过第1、2种内存溢出问题。
下面来分享下,我排查问题的思路及过程。
网上大多数的博客和文章,写的都是修改运行内存,我都试了一下,根本无效,废弃方案如下:
- 修改 IDEA 中的 Run 配置项修改 VM options:-Xmx512m -Xmx1024m(改完比之前运行时间还短)
- 修改 IDEA 中 Compiler 的 Build process heap size(Mbytes): 修改为 1024 或者 2048(并没有什么用)
- 修改 IDEA 中的 Build Tools—>maven—>Importing 将 VM options for importer 修改为-Xms1024m -Xmx2048m(并没有什么用)
- 修改 IDEA 的 bin 目录下的 idea64.exe.vmoptions,修改内容如下:
-Xms2048m
-Xmx2048m
-Xverify:none
-XX:+DisableExplicitGC
-XX:MetaspaceSize=512m
这样的修改只能使得IDEA的启动、编译变快及整个程序的运行时间变长了,结果程序依然报错。
- 修改JVM启动参数,对于IDEA启动运行,无用
以上方案,全部无效,即便生效也不会考虑,因为打包成应用程序以后,脱离 IDE执行,还会遇到类似的问题,那么就只能接着往下找解决方案。
黔驴技穷的我,突然想到之前性能测试,看到过同事通过JDK自带工具jvisualvm,进行GC调优,结果还真的用上了。
如何操作
找到JDK安装目录 bin 下的 jvisualvm.exe,双击打开,如下图所示。
运行你要监控的程序,双击左侧运行程序,工具中会显示程序的运行情况,只保留内存,其他不选,如下图所示。
内存溢出,所以我们暂时只关注内存就可以了,内存会显示运行时堆内数据的变化,如对象实例等。
接着是内心等待,查看监控内存情况,结果看到最大内存瞬间增长好几倍,如下图所示。
最大内存瞬间暴涨好几倍,而且程序同时抛出如下异常。
问题定位出来了,接下来就是复现查找问题了。
将运行参数调整-Xmx216m,再次运行程序,同步骤 1、2,点击堆 dump, 进入监控界面,点击切换至类选项卡如下图所示。
终于被我找到这小子了,原来是它搞的鬼,创建了9314个char数组对象。
双击这个类名,找到问题如下图所示。
找到问题后,接下来就是优化程序的事了。
解决方案
经过以上的排查,找到了问题的原因,是因为写数据时超过允许最大行数导致的溢出,最后采取分段写入,完美解决了这个问题。
虽然解决了内存溢出问题,但程序的执行依然很慢,后来又找到了大数据的写入数据方法,经过程序的再次优化,260W数据全部写完仅需54秒,真的是 VERY NICE!
以上就是我排查问题的整个过程,当然这个案例的代码是为了模拟内存溢出写的一段程序,非业务代码,仅供参考的入门案例。
写在最后
jvisualvm、 jprofile 真的是一个内存优化、排查问题的一个好工具,可以说是写程序必备神器。
关于内存溢出问题的文章很多,对我而言,能用上的真的是少之又少,作为一个测试喵并不敢造次和评价,有兴趣的同学可以去买本书去深入学习了解。
这里要特别感谢强哥的帮助,每次都能给我很多的思路和灵感,让我受益良多。
强哥
之前北京同事,多年经验高级JAVA开发工程师
参考文章
解决项目中java heap space的问题[1]
记一次解决OutOfMemoryError: Java heap space详细过程与解决思路[2]
参考资料
[1]
解决项目中java heap space的问题: https://blog.csdn.net/smh0310/article/details/90664598
[2]
记一次解决OutOfMemoryError: Java heap space详细过程与解决思路: https://blog.csdn.net/lyflyyvip/article/details/82288719
- mysqldump的简单使用
- mac:在当前文件夹打开terminal终端
- 斯诺登研发黑客警报App上架 监测功能引发争议
- JMS + jboss EAP 6.2 示例
- Maven Compilation error [package org.testng.annotations does not exist]
- 查看jar包的jdk版本并降级
- ejb3: message drive bean(MDB)示例
- java提示找不到或无法加载主类
- 学Java有什么好方法?刻苦学技术让我最终成为自信的码农
- expect+scp传输文件发现文件丢失
- IBM WebSphere MQ 7.5基本用法
- QPS的计算
- Django----中间件详解
- linux 添加用户到sudo中
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法