一次线上OOM问题排查与解决

前言:最近维护的一个项目在正式环境出现了OutOfMemeryError错误,导致项目不能访问,本篇文章记录一下问题的排查过程以及解决办法。

一、解决思路

发生OOM错误一般情况都是堆内存不足导致的,要查看具体的发生OOM时堆内存的情况,需要把它dump到本地,然后通过一些工具进行分析,才能大概的发现问题出在哪里。

二、dump文件

使用java自带的jmap命令,生成 hprof文件。
jmap -dump:format=b,file=dump.hprof 23322 其中23322是当前java进程的进程号,可以通过jps -l命令查看。

三、使用mat工具分析 hprof文件

mat分析完后,给出了可能出现的问题如下

image.png

很明显,当前对内存中有两个类型的对象几乎占满了整个堆内存,一个是byte[]数组,一个是Http11OutputBuffer对象。查看details,发现这两个问题都来自于tomcat
image.png

image.png

进一步打开Histogram

image.png

第一行,byte[]数组有2612个,占据了840007864(约800M)的空间,基本上可以确定是它导致了OOM问题。
再查看byte[]List Objects
image.png

可以看到,byte[]都是来自于请求get请求。
分析问题:正常的get请求tomcat不可能会创建这么大的对象,而且每次创建的byte[]大小都相同,一定是哪里配置了。突然想起来之前项目有个导出功能,如果选择的条数过多的话,后台会提示Request header is too large错误,查阅资料发现是tomcat对请求头的大小做了限制,于是我修改了server.xml的配置,将maxHttpHeaderSize一点点调大了,设置为83886080,正好与byte[]数组的大小相同,问题找到了。
将配置删除后,问题就解决了。
后记::其实当线上发现这个问题的时候,我通过-Xms-Xmx直接调大了堆内存的大小,问题就没有再出现了,这也是大多数人解决OOM问题的办法。

你可能感兴趣的:(一次线上OOM问题排查与解决)