OOM别慌,手把手教你定位

编程入门 行业动态 更新时间:2024-10-09 22:15:57

OOM别慌,<a href=https://www.elefans.com/category/jswz/34/1768412.html style=手把手教你定位"/>

OOM别慌,手把手教你定位

本渣渣今早正在写BUG呢,TL丢过来一个问题,说是平台有异常让我康康。一顿操作找到错误日志后,傻眼了OutOfMemoryError,这玩意我也就会写写,也没定位过啊。

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.OutOfMemoryError: Java heap spaceat org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:446)at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378)at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:475)	
Caused by: java.lang.OutOfMemoryError: Java heap space

于是习惯性的打开了百度。再看了若干经验之谈后,准备下手了。步骤如下:

  1. 先找到服务器下oom错误快照
  2. 使用工具分析错误原因
  3. 结合代码定位到异常发生的地方

查找错误快照

不明白heap dump的看这个:

我的是在这里

 当然可以通过find命令来查找,一般都在tomcat的目录下

以hprof结尾的就是目标文件了

使用工具分析

MemoryAnalyzer.exe

下载链接:.php(建议科学上网,70M左右)

打开之后,把上一步找到的快照文件导进去。注意可能有坑(一般线上环境的快照文件动辄上G,所以建议把工具的最大内存调大,如下)

MemoryAnalyzer.ini文件,我的文件有4.1G所以调的比较大。

-startup
plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.700.v20180518-1200
-vmargs
-Xmx5096m

 成功导入之后会到欢迎界面,忽略就行。点击分析产生的Leak Suspects,如图:

其中Histogram比较常用:

 占用内存排行,对于定位也很有帮助。饼图下方有存在的错误报错,自动生成的,主要是把占用内存高的展示出来了,意思就是你的问题在这里。

先看堆栈信息,找到报错的地方,这里会有具体的报错方法的信息(我没截全):

 再看是什么对象导致的,点details

可以看到一共有接近1千万的对象,后面的内存占用也有,那么到这一步,可以去代码里面找了。

查找代码

 @Overridepublic List<ResourceResp> queryResources(ResourcesVerifyReq resourcesVerifyReq) {try {ResponseData responseData;long total = 1001;HashMap<String, Object> queryParam = new HashMap<>(8);int pageNo = resourcesVerifyReq.getPageNo();queryParam.put("pageNo", pageNo);int pageSize = resourcesVerifyReq.getPageSize();queryParam.put("pageSize", pageSize);if (pageSize > 0) {responseData = RpcExchange.call(rpcParamDto,  queryParam,  Constants.HTTP_WEB_PORT);} else {pageSize = 1000;queryParam.put("pageSize", pageSize);while ((long) pageNo * (long) pageSize < total) {responseData = RpcExchange.call(rpcParamDto, queryParam,  Constants.HTTP_WEB_PORT);List<ResourceResp> list = data.getList();total = data.getTotal();returnData.addAll(list);}}return returnData;} catch (Exception e) {logger.error("资源查询出错",e);}}
// 相信你们看到这个while循环,心里也咯噔了一下,原来当查询后total大于1000时,这里就进入死循环了,原因竟然是,分页去查的时候,pageNo没进行递增的操作。

修改如下:

while ((long) pageNo * (long) pageSize < total) {responseData = RpcExchange.call(rpcParamDto, queryParam,  Constants.HTTP_WEB_PORT);List<ResourceResp> list = data.getList();total = data.getTotal();returnData.addAll(list);// 大于1000时,需要递增queryParam.put("pageNo", ++pageNo);}

 总结如下:

// 1,写循环的时候,尽量考虑考虑次数是否明确,终止条件是否确定,小心死循环,小心死循环,小心死循环
// 2,定位OOM时,不用慌,工具其实替我们做了大量的工作,但你要会使用,我只是刚用了下皮毛
// 3,review的时候,多注意可能导致死循环的地方
// 4,OOM的定位,还有别的很强大的工具,需要去多接触

 

 

更多推荐

OOM别慌,手把手教你定位

本文发布于:2024-03-13 14:13:56,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1734160.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:手把手教你   OOM

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!