前言:最近維護(hù)的一個(gè)項(xiàng)目在正式環(huán)境出現(xiàn)了OutOfMemeryError錯(cuò)誤,導(dǎo)致項(xiàng)目不能訪(fǎng)問(wèn),本篇文章記錄一下問(wèn)題的排查過(guò)程以及解決辦法。
一、解決思路
發(fā)生OOM錯(cuò)誤一般情況都是堆內(nèi)存不足導(dǎo)致的,要查看具體的發(fā)生OOM時(shí)堆內(nèi)存的情況,需要把它dump到本地,然后通過(guò)一些工具進(jìn)行分析,才能大概的發(fā)現(xiàn)問(wèn)題出在哪里。
二、dump文件
使用java自帶的jmap命令,生成 hprof文件。
jmap -dump:format=b,file=dump.hprof 23322 其中23322是當(dāng)前java進(jìn)程的進(jìn)程號(hào),可以通過(guò)jps -l命令查看。
三、使用mat工具分析 hprof文件
mat分析完后,給出了可能出現(xiàn)的問(wèn)題如下

image.png
很明顯,當(dāng)前對(duì)內(nèi)存中有兩個(gè)類(lèi)型的對(duì)象幾乎占滿(mǎn)了整個(gè)堆內(nèi)存,一個(gè)是
byte[]數(shù)組,一個(gè)是Http11OutputBuffer對(duì)象。查看details,發(fā)現(xiàn)這兩個(gè)問(wèn)題都來(lái)自于tomcat。
image.png

image.png
進(jìn)一步打開(kāi)Histogram

image.png
第一行,
byte[]數(shù)組有2612個(gè),占據(jù)了840007864(約800M)的空間,基本上可以確定是它導(dǎo)致了OOM問(wèn)題。再查看
byte[]的List Objects
image.png
可以看到,
byte[]都是來(lái)自于請(qǐng)求get請(qǐng)求。分析問(wèn)題:正常的get請(qǐng)求
tomcat不可能會(huì)創(chuàng)建這么大的對(duì)象,而且每次創(chuàng)建的byte[]大小都相同,一定是哪里配置了。突然想起來(lái)之前項(xiàng)目有個(gè)導(dǎo)出功能,如果選擇的條數(shù)過(guò)多的話(huà),后臺(tái)會(huì)提示Request header is too large錯(cuò)誤,查閱資料發(fā)現(xiàn)是tomcat對(duì)請(qǐng)求頭的大小做了限制,于是我修改了server.xml的配置,將maxHttpHeaderSize一點(diǎn)點(diǎn)調(diào)大了,設(shè)置為83886080,正好與byte[]數(shù)組的大小相同,問(wèn)題找到了。將配置刪除后,問(wèn)題就解決了。
后記::其實(shí)當(dāng)線(xiàn)上發(fā)現(xiàn)這個(gè)問(wèn)題的時(shí)候,我通過(guò)
-Xms和-Xmx直接調(diào)大了堆內(nèi)存的大小,問(wèn)題就沒(méi)有再出現(xiàn)了,這也是大多數(shù)人解決OOM問(wèn)題的辦法。