事故背景

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

一看项目日志今天的都几个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

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

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

注意理解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,控制台也会打印信息。

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

除了上面加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

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

记一次线上环境的内存溢出(java.lang.OutOfMemoryError)的更多相关文章

  1. 记一次内存溢出java.lang.OutOfMemoryError: unable to create new native thread

    一.问题: 春节将至,系统访问量进入高峰期.随之系统出现了异常:java.lang.OutOfMemoryError: unable to create new native thread.在解决这个 ...

  2. Tomcat内存溢出(java.lang.OutOfMemoryError: PermGen space)

    Tomcat启动时报如下错误:     java.lang.OutOfMemoryError: PermGen space 解决办法:     配置相关内存大小.其中按照启动tomcat的不同方式,分 ...

  3. Tomcat内存溢出(java.lang.OutOfMemoryError: PermGen space)的解决办法

    Tomcat启动时报如下错误: java.lang.OutOfMemoryError: PermGen space 解决办法: 配置相关内存大小.其中按照启动tomcat的不同方式,分如下三种情况 a ...

  4. android内存溢出 java.lang.OutOfMemoryError

    今天在做ListView 的时候.想做一个音乐列表模块,前面是图片,后面是分类名称,如下图: 结果运行时候,LogCat是总是报 java.lang.OutOfMemoryError的错误,顾名思义, ...

  5. Java内存溢出java.lang.OutOfMemoryError: PermGen space

    今天把以前的一个项目部署在tomcat,启动没问题.因为用到了webservice,当调用webservice中的方法时一直报内存溢出异常 Exception in thread "http ...

  6. tomcat7 内存溢出 java.lang.OutOfMemoryError: Java heap space

    在{tomcat7_home}bin/catalina.sh最上面添加: JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=128M -XX ...

  7. tomcat7 内存溢出 java.lang.OutOfMemoryError 处理方法

    找到tomcat的安装目录,在  tomcat安装目录/bin/catalina.sh最上面添加: JAVA_OPTS="-server -Xms800m -Xmx800m -XX:Perm ...

  8. 解决eclipse maven install 造成JVM 内存溢出(java.lang.OutOfMemoryError: Java heap space)

    maven install 报错信息: The system is out of resources.Consult the following stack trace for details.jav ...

  9. 记一次线上环境 ES 主分片为分配故障

    故障前提 ElasticSearch 版本:5.2 集群节点数:5 索引主分片数:5 索引分片副本数:1 线上环境ES存储的数据量很大,当天由于存储故障,导致一时间 5个节点的 ES 集群,同时有两个 ...

随机推荐

  1. [Lydsy1706月赛]大根堆

    4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 358  Solved: 150[Submit][Stat ...

  2. google 上网

    https://chrome.google.com/webstore/detail/%E5%BC%80%E7%9C%BC/kpamljbkjaaljbcgobdealnpalcgicna?hl=zh- ...

  3. 使用Guava适配不同的callback

    Cache<Key,Value> cache =CacheBuilder.newBuilder() .maximumSize(1000) .build();// look Ma, no C ...

  4. iOS用户体验之-modal上下文

    iOS用户体验之-modal上下文 何为模态视图,它的作用时聚焦当前.获得用户的注意,用户仅仅有完毕模态的任务才 退出模态视图.否则你将不能运行app的任务,比如,alert view,model v ...

  5. C语言最小生成树prim算法(USACO3.1)

    /* ID: hk945801 LANG: C++ TASK: agrinet */ #include<iostream> #include<cstdio> using nam ...

  6. SQL Server中一些有用的日期sql语句

    SQL Server中一些有用的日期sql语句 1.一个月第一天的 SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) 2.本周的星期一 SELECT DA ...

  7. [IT学习]转载python 项目 计算器

    这个是从网上搜到的Python小项目之计算器(原文地址:http://www.2cto.com/kf/201402/279637.html).但该段代码估计是Python 2 写的. 如果你使用的程序 ...

  8. SQL外键的作用

    貌似很有用,但没有真正用过: SQL的主键和外键的作用: 外键取值规则:空值或参照的主键值. (1)插入非空值时,如果主键表中没有这个值,则不能插入. (2)更新时,不能改为主键表中没有的值. (3) ...

  9. swift中的@objc的作用

    转载:https://www.jianshu.com/p/6c5b45d9d042 自动清除冗余代码减小包大小 得益于 Swift 的静态语言特性,每个函数的调用在编译期间就可以确定.因此在编译完成后 ...

  10. JDK安装以及配置环境变量的步骤

    ---恢复内容开始--- 一.JDK安装 JDK下载链接:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads ...