通用mapper模糊查询_最近,客户说风控项目有个别用户查询不到数据,原来是......

风控项目中,由于通用mapper的无条件查询导致内存溢出。当record.getTrxNo()为null时,查询全表数据,占用大量内存。解决方法是在查询前添加判断条件。文章总结了内存溢出的原因,并介绍了如何生成和分析dump文件,以定位问题。
摘要由CSDN通过智能技术生成

54bc14de08f25507cfa839c9d8ec5abd.png

事故背景

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

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

be3bb26791fff7f4b4dfe404ec4f568f.png

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

d025d4e602e0706dcbe099196befc37c.png

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

1ad35ee5778ed2f07008696efd0f1661.png

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

但是这里就出现了一个问题,如果record.getTrxNo()是null的话(注意红框标注的部分之前是没有的)就相当于没有条件了,就会查询全表的数据。关注公众号Java面试那些事儿,回复关键字面试,获取最新的面试资料。我看了下数据库,对应的表数据大概有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) {        Listlist = new ArrayList();        while (true){            list.add(new OOMObject());        }    }}

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

77efb950dff582084bc795d51341cad8.png

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

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

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

或者

jmap -dump:live,file=/path/to/heap_dump.hprof process_id

# 分析dump文件的工具

  • IBM Memory Analyzer

  • Eclipse Memory Analysis

e4b4adfb6716e6e9b6f7a7b465d26c46.png

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

作者:十年磨一剑 来源:https://www.cnblogs.com/2YSP/p/9300648.html

 往期推荐 

?

  • 太火了,这些牛逼的Java代码技巧,肯定能让你目瞪口呆!
  • 分布式系统事务一致性
  • 笑一笑:上班是什么体验?
 

点击

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值