前段时间换了工作,进公司3、4个月内,我的团队主要负责DSP系统,在DSP里面主要做dist-ordersservice。先说说DSP是干什么的。项目组所在的公司主要从事医药行业,淘宝、天猫、京东……很多渠道都有自己的店铺,也有一套ERP,主要是进销存。DSP是负责对接ERP和各种渠道传递信息的,订单和库存是什么。。。几周前,领导收到一封上线的某机系统OOM的邮件,领导直接扔给并叫我有空的时候去查一下。查完直接去堡垒机上服务器查,开始各种乱七八糟的命令,什么top,jstack,jinfo,jstat,jmap……结果发现一个都不管用,不是因为命令不起作用,但因为我无权查看它们。……更何况我就是不知道申请什么样的许可。就算知道,运维已经重启了,所以还是要查屁,希望只能放在heapdump文件上。堡垒机在服务器上可以下载文件,但是文件太大了,超过6G,我根本下载不了。向运维团队的同事求助,发邮件,拉群,在我的努力下终于给了我。废话不多说,直接上jdk自带的jvisualvm软件进行分析,(jvisualvm在你安装jdk的bin目录下)交给jvisualvm分析分析。我的电脑16G内存,6G的heapdump文件我差点分析不出来。Sendmycomputeraway...这里除了OOM线程和系统属性外没有什么重要信息。点击显示系统属性,发现JVM没有设置任何参数(最大堆,最小堆,GC参数等)我们看类,发现char[]和String占了大部分,双击char[],进去看看emmm,不知道怎么回事,有些地方是乱码,暂时没看到有用的信息。看了半天,终于决定用IBMheapanalyzer试试另一个软件(下载地址:https://www.ibm.com/support/pages/node/1109955?mhsrc=ibmsearch_a&mhq=heapanalyzer)是一个jar打包,直接java-jar-startXmx15gxxx.jar(这里-Xmx的内存大小自己定,如果分析过程中OOM就是你给的内存太少了),也可以写个启动脚本加载heapdump文件,最后这个是貌似他这里有疑似泄漏,就是DisOrderItemBO对象占用内存2.8G,约占58.74%。再看ArrayList。大致猜测是ArrayList加载了过多的DisOrderItemBO对象,无法以树状结构显示:没有运行,因为ArrayList集合中的DisOrderItemBO元素过多。见分析可知,DisOrderItemBO实例共有1,936,459个,共占用内存2G多。好像已经得到结果了,但其实还是不知道从何下手,因为DisOrderItemBO用的地方太多了,不知道是哪里引起的。于是,我另外一个软件,MemoryAnalyzer(下载地址:https://www.eclipse.org/downloads/download.php?file=/mat/1.12.0/rcp/MemoryAnalyzer-1.12.0.20210602-win32.win32.x86_64。zip)是这样加载的。这里也有疑似内存泄漏的地方。点击查看,列出详细信息:一是哪个线程有问题,二是哪些对象导致内存增长无法恢复。发现与前面软件分析的结果类似,ArrayList集合中的DisOrderItemBO元素过多。现在知道DisOrderItemBO对象太多了(在一个线程中),无法回收。ArrayList直接丢弃,因为它本身没有问题,只是携带了太多的DisOrderItemBO对象,现在我只需要知道它是哪个线程,就这个软件能看到(可能前两个也能看到,我没找到)http-nio-7210-exec-9thread,如果我没记错的话,应该是Tomcat任务线程池的线程。现在我可以确认一件事,那就是肯定不是系统中的异步任务或者JOB等导致OOM的。其实这里已经给出了答案,怪我懒惰。没继续看跟帖信息。给出了我的Service对应的类的完整包名和对应的controller的完整包名。直接根据资料找到了代码,稍微摸了一下代码逻辑,本地启动试试,我去在线日志touch一条请求消息,用postman请求。试了几次,我怎么玩,DisOrderItemBO对象都不多。然后我想,如果参数为空(原代码是不会检查需要的参数),我试了一下,console打出sql后,拿到线上DB执行sql去掉不需要的查询列,并排序,只看数字(一条数据对应一个DisOrderItemBO例子),同理,如果把上面分析的1,936,459个例子都找出来了,那么就走上正轨了。为了严谨,我在where条件里加了一个创建时间,时间过期在这个heap生成dump文件的前10分钟(发生OOM时生成的heapdump文件会很慢),1,936,374块的数据被查询。虽然不正确,但也没有多少错误。现在看来,差距还不错。除了这里的问题,虽然我找到了,但问题是这个接口是查询订单明细的。在页面操作时,不能有必填参数(订单主体ID)。这个问题一直想不通......如果过了几个星期半个月,我还没有更新文章继续调查,就说明这个问题已经完美解决了
