记录一次OOM堆内存溢出
2018-01-25 19:24
169 查看
事件概述
页面点击导出所有数据, 由于数据量过大,消费方通过分页查询的方式从服务方分页获取所有数据,存放在list中。 然后将list中大概六万条数据转化为Excel文件下载, 此时发生java.lang.OutOfMemoryError: Java heap space,堆内存溢出。
/** * 分页查询获取所有的数据 * * @param pageReqForTop * @param employeePartyId * @param totalRow 总记录数 * @return * @throws Exception * @author ex-huangyajun 2018年01月20日 15:11 */ private List<EquipDateMaintainVo> getEquipDateMaintainVoListPage(PageReqForTop<EquipDateMaintainVo> pageReqForTop, Long employeePartyId, Integer totalRow) throws Exception{ List<EquipDateMaintainVo> exportList = new ArrayList<>(); //每页查询的数量 final int pageSize = 5000; //计算页数 int totalPage = (totalRow - 1) / pageSize + 1; logger.info("---查询总的记录数 totalRow = {},计算页数 totalPage = {}, 每页显示行数 pageSize = {}", totalRow, totalPage, pageSize); for (int curPage = 0; curPage < totalPage; curPage++) { //当前页起始行 pageReqForTop.setCurPage(curPage + 1); pageReqForTop.setPageSize(pageSize); Response<PageResForTop<List<EquipDateMaintainVo>>> result = equipDateMaintainServiceClient .pageEquipDateMaintain(pageReqForTop, employeePartyId); if (result == null || result.getResult() == null) { return null; } if (result.getCode() != FacadeEnums.OK.code) { throw new BizException(result.getMsg()); } List<EquipDateMaintainVo> list = result.getResult().getData(); exportList.addAll(list); logger.info("---分页导出,第【{}】次查询成功,查询出List size = 【{}】", curPage + 1, list.size()); } logger.info("---已经将所有数据封装到exportList ,exportList.size = {}", exportList.size()); return exportList; }
如何查出问题所在:
打开linux控制台:
$ jps //是JDK 1.5提供的一个显示当前所有java进程pid的命令 28461 Jps 22153 Bootstrap
$ jstat -gcutil 22153 1000 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 5.39 13.39 25.25 99.78 57 1.048 9 1.733 2.781 0.00 5.39 13.39 25.25 99.78 57 1.048 9 1.733 2.781 //S0 — 年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 //S1 — 年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 //E — 年轻代中Eden(伊甸园)已使用的占当前容量百分比 //O — Heap上的 Old space 区已使用空间的百分比 //P — Perm space 区已使用空间的百分比 //YGC — 从应用程序启动到采样时发生 Young GC 的次数 //YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒) //FGC — 从应用程序启动到采样时发生 Full GC 的次数 //FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒) //GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
$ jstat -gc 22153 1000 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 17472.0 17472.0 0.0 941.9 139776.0 18776.8 349568.0 88272.3 70528.0 70375.1 57 1.048 9 1.733 2.781 17472.0 17472.0 0.0 941.9 139776.0 18776.8 349568.0 88272.3 70528.0 70375.1 57 1.048 9 1.733 2.781
查看java 堆(heap)使用情况,执行命令:
$ jmap -heap 22153
Attaching to process ID 22153, please wait... Debugger attached successfully. Server compiler detected. JVM version is 24.79-b02 using thread-local object allocation. Mark Sweep Compact GC //GC 方式 Heap Configuration: //堆内存初始化配置 MinHeapFreeRatio = 0 //对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40) MaxHeapFreeRatio = 100 //对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70) MaxHeapSize = 2082471936 (1986.0MB) //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小 NewSize = 1310720 (1.25MB)//对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小 MaxNewSize = 17592186044415 MB//对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小 OldSize = 5439488 (5.1875MB)//对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小 NewRatio = 2 //对应jvm启动参数-XX:NewRatio=:‘新生代’和‘老生代’的大小比率 SurvivorRatio = 8 //对应jvm启动参数-XX:SurvivorRatio=设置年轻代中Eden区与Survivor区的大小比值 PermSize = 21757952 (20.75MB) //对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小 MaxPermSize = 85983232 (82.0MB)//对应jvm启动参数-XX:MaxPermSize=<value>:设置JVM堆的‘永生代’的最大大小 G1HeapRegionSize = 0 (0.0MB) Heap Usage://堆内存使用情况 PS Young Generation Eden Space://Eden区内存分布 capacity = 33030144 (31.5MB)//Eden区总容量 used = 1524040 (1.4534378051757812MB) //Eden区已使用 free = 31506104 (30.04656219482422MB) //Eden区剩余容量 4.614088270399305% used //Eden区使用比率 From Space: //其中一个Survivor区的内存分布 capacity = 5242880 (5.0MB) used = 0 (0.0MB) free = 5242880 (5.0MB) 0.0% used To Space: //另一个Survivor区的内存分布 capacity = 5242880 (5.0MB) used = 0 (0.0MB) free = 5242880 (5.0MB) 0.0% used PS Old Generation //当前的Old区内存分布 capacity = 86507520 (82.5MB) used = 0 (0.0MB) free = 86507520 (82.5MB) 0.0% used PS Perm Generation//当前的 “永生代” 内存分布 capacity = 22020096 (21.0MB) used = 2496528 (2.3808746337890625MB) free = 19523568 (18.619125366210938MB) 11.337498256138392% used 670 interned Strings occupying 43720 bytes.
histo[:live] 打印每个class的实例数目,内存占用,类全名信息. VM的内部类名字开头会加上前缀”*”. 如果live子参数加上后,只统计活的对象数量.
$ jmap -histo:live 22153 num #instances #bytes class name ---------------------------------------------- 1: 65220 9755240 <constMethodKlass> 2: 65220 8880384 <methodKlass> 3: 11721 8252112 [B 4: 6300 6784040 <constantPoolKlass> 5: 75224 6218208 [C 6: 93969 5163280 <symbolKlass>
最后,修改配置文件增大堆内存:
$ cd /opt/apache-tomcat-8.0.23/bin 打开catalina.sh文件,添加JAVA_OPTS: CATALINA_OPTS="$CATALINA_OPTS $UI_DEBUG" JAVA_OPTS="-Xms512m -Xmx512m -server" # OS specific support. $var _must_ be set to either true or false. cygwin=false
相关文章推荐
- tomcat内存溢出问题记录
- tomcat 内存溢出错误记录
- jmeter内存溢出因素与处理方式记录
- 详细记录一下JAVA应用程序服务出现内存溢出的利用MAT分析过程
- (转)Jmeter内存溢出处理方式记录
- tomcat内存溢出问题记录
- Jmeter内存溢出因素与处理方式记录
- android开发内存溢出处理记录
- tomcat内存溢出问题记录
- 错误记录之内存溢出
- JVM内存溢出与排错
- Android高级开发第一讲--如何在Android应用中避免内存溢出OOM问题
- iis应用程序池 内存溢出错误 System.OutOfMemoryException
- JVM - 内存溢出问题排查相关命令jcmd jmap
- jvm内存溢出实例一
- [教程] 【转】Android 通过软引用实现图片缓存,防止内存溢出 [复制链接]
- [z]TOMCAT内存_JVM参数设置解决溢出
- npm 内存溢出
- 内存溢出的三种情况及解决办法分析
- Tomcat中JVM内存溢出及合理配置