现象
公司新上线的一个数据入库服务,部署在各个项目上,其中一个项目(其它项目上运行正常)经常反馈服务不稳定,运行几天会出现数据无法入库的情况,在看过几次反馈回来的日志发现都是内存溢出。
排查过程
因为只有这个项目上出现这种情况,初步认为是该项目上数据量较大,调整了tomcat内存大小
打开tomcat的bin目录下的catalins.sh文件
在cygwin=false之上
添加以下语句
JAVA_OPTS="-Xms1024m -Xmx4096m -Xss1024K -XX:PermSize=512m -XX:MaxPermSize=2048m"
在调整过内存大小后两天,还是出现了内存溢出,这次怀疑可能是程序出了问题,只是因为数据的不同其他项目上没有暴露出来而已
线上排查
通过jmap -histo PID 命令查看内存中保留的对象
通过这个能看出有很大的数组占用着内存
Eclipse Memory Analyzer工具离线分析
此时要具体看是哪个对象就需要dump内存下来,利用工具离线分析
dump命令是 jmap -dump:format=b,file=/opt/heap.hprof PID
dump下来后将文件拷贝到本地
我在分析的时候一开始用的是jdk自带的java VisualVM,可能是对于工具不是很熟悉,未找到直观的展示,改用Eclipse Memory Analyzer(下载地址:https://www.eclipse.org/mat/downloads.php)
打开后导入dump文件
打开首页,不得不说eclipse mat真是个好东西,在你一筹莫展的时候,直接饼状图展示出来,一目了然,通过饼状图可以看出内存中主要的问题,点开详情
可以清晰的看出程序哪里占用内存情况,根据mat中指出的位置,检查了代码发现代码里一处容器在每次处理数据后没有释放,正好此类数据在大部分项目上都没有,所以其他项目没发现这个问题。
修改了代码后更新到项目上,观察了两周的时间,服务运行稳定,未出现异常,问题解决!