记一次线上环境的内存溢出(java.lang.OutOfMemoryError)

摘要:
使用free m命令发现服务器的4g内存几乎已满。259ERROR]:846)atjavax.servlet.http.HttpServlet.service(HttpServlet.java:123)atorg.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:
事故背景

今天客户说风控项目有个别用户查询不到数据不是报错就是一直卡在那里,我就去那个接口看了下。

一看项目日志今天的都几个g了,平常也就几百兆吧,很明显出了问题。

请求接口后使用命令tail -f 实时查看日志,发现有个东西一个在刷屏,几分钟了还在刷。

把日志切割后查看还发现了堆内存溢出错误,使用命令 free -m 发现服务器4g内存几乎已经占满了。

[2018-07-12 14:06:46,259 ERROR]:[http-bio-443-exec-12] - 错误提示 :org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Java heap space
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:978)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.OutOfMemoryError: Java heap space

记一次线上环境的内存溢出(java.lang.OutOfMemoryError)第1张

就是这个loanInfos对象,于是猜想应该是如下这个方法出问题了。

记一次线上环境的内存溢出(java.lang.OutOfMemoryError)第2张

再进去看doNoFindUserReq()这个方法。。。

记一次线上环境的内存溢出(java.lang.OutOfMemoryError)第3张

注意理解noLoanInfosMapper.select()方法,用过通用mapper插件的应该知道这是根据实体类里的属性进行查询。

但是这里就出现了一个问题,如果record.getTrxNo()是null的话(注意红框标注的部分之前是没有的)就相当于没有条件了,就会查询全表的数据。我看了下数据库,对应的表数据大概有17万行,也就是创建了17W个NoLoanInfos对象,所以堆内存都被用光了。

而且后面还有针对这个list的for循环操作。。。

解决办法就是添加了一个判断条件。

总结一下,导致java.lang.OutOfMemoryError内存溢出的几个原因:

1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
3.代码中存在死循环或循环产生过多重复的对象实体;
4.使用的第三方软件中的BUG;
5.启动参数内存值设定的过小;

更多可以参考这里:http://outofmemory.cn/c/java-outOfMemoryError

其实,我这里写的很简单,但当时没处理过这种情况也是折腾了半天,还要被客户不停地催,不过好在下次就有经验了。

补充,可以通过更专业的方法来分析。

生成dump文件

首先,添加jvm参数生成dump文件和打印堆栈信息。

package cn.sp.chapter2;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: 2YSP
 * @Description: java堆内存溢出异常测试
 * @Date: Created in 2018/1/15
 */
public class HeapOOM {

    static class OOMObject{

    }

    /**
     * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=E:file
     * @param args
     */
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<OOMObject>();
        while (true){
            list.add(new OOMObject());
        }
    }
}

运行后对应文件夹生成dump文件java_pid11708.hprof,控制台也会打印信息。

记一次线上环境的内存溢出(java.lang.OutOfMemoryError)第4张

这样很容易看出哪里出问题了。

除了上面加jvm参数的方式,还可以通过命令手动生成堆文件。

jcmd process_id GC.heap_dump /path/to/heap_dump.hprof

或者

jmap -dump:live,file=/path/to/heap_dump.hprof process_id
分析dump文件的工具

1.IBM Memory Analyzer

2.Eclipse Memory Analysis

记一次线上环境的内存溢出(java.lang.OutOfMemoryError)第5张

很容易看出是OOMObject这个对象占据了大部分堆内存。

免责声明:文章转载自《记一次线上环境的内存溢出(java.lang.OutOfMemoryError)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇扩展WinForm的ComboBoxwebpack.config.js 参数简单了解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Manjaro安装后简单配置

一个相见恨晚的Linux操作系统 Manjaro到底有多受欢迎? DistroWatch是一个包含了各种Linux发行版及其他自由/开放源代码的类Unix操作系统。 (如OpenSolaris、MINIX及BSD等)的新闻、人气排名、以及其他一般信息等的网站。 它包含了数百种发行版的信息。 原文链接:https://distrowatch.com/t...

linux 下文件恢复工具extundelete介绍

        下载http://extundelete.sourceforge.net/ bunzip2 extundelete-0.2.0.tar.bz2 tar xvf extundelete-0.2.0.tar cd extundelete-0.2.0 make make install   [root@yznvm1 yzn]# df文件系统  ...

图文讲解:iOS App提交流程

原文:http://www.toceansoft.com/ios/3287.jhtml 一、证书的导出   1.1、前期工作 首先你需要有一个苹果的开发者帐号,一个Mac系统。 如果没有帐号可以在打开http://developer.apple.com/申请加入苹果的开发者计划。支付99美元每年,怎么申请网上有详细的介绍,在此不多做介绍。 如果你已经有了一...

.deb文件打包

最近因项目需要,需要把文件夹打包为.deb格式的包,幸亏一位朋友帮忙指导了我一个晚上,才得以完成,这里再次对他表示感谢。 整理打包流程如下: 请先参考此博客内容,了解deb文件打包 如何制作Deb包和相应的软件仓库,其实这个很简单。这里推荐使用dpkg来进行deb包的创建、编辑和制作。 首先了解一下deb包的文件结构: deb 软件包里面的结构:它具有D...

Linux的ssh监听多个端口

背景 今天有两台内网机器需要用到ssh远程登录操作,但是网络策略不通,申请网络策略也被拒绝,原因是不允许申请ssh的常用登录端口。于是灵机一动,直接把ssh监听多个端口,其中一个是非常用端口,然后网络策略申请到这个端口,不就可以了嘛,机制的一批。 修改过程 首先备份好原有的sshd的配置文件 cp /etc/ssh/ssh_config /etc/ssh/...

vim 让人爱不释手的编辑器之神

VIM 基本介绍 vim诞生已有20多年,它常被人称之为编辑器之神,vim的操作理念可以说是独具一格而又出类拔萃,使用vim能极大的提升文本处理效率,因此熟练掌握vim应该是每个程序员都应该做到的事情。 vim目前有3个较常见的版本: vi:只保留了一些基础功能,在绝大多数Linux发行版中都内置了vi vim:相较于vi功能更加完善,是标准的版本,但是...