记一次内存溢出及解决办法

情景描述:

最近线上系统发送邮件失败,通过查日志发现多台邮件服务器出现内存溢出(即java.lang.OutOfMemoryError错误),并且tomcat进程也已经停掉。

解决思路:

先重启tomcat,保证服务器可用,下载HeapDumpPath指定的dump文件并使用Jprofiler进行分析,找出占用内存比较大的对象。 直接到Biggest Objects,截图如下: 记一次内存溢出及解决办法 发现top 10是10个数组,而且数组占用大小都是相同的,有167M,这个值得注意。于是,继续分析,其中的每个数组,选择相应的数组对象,并点击"Show In graph", 查看Java stack调用信息,发现相应线程为"http-nio-8083-exec-29", 记一次内存溢出及解决办法记一次内存溢出及解决办法 注意绿色框标识的相应线程信息,于是到Thread Dump查看 线程"http-nio-8083-exec-29"的相关堆栈调用信息: 记一次内存溢出及解决办法 红色箭头指向的方法即为我们系统自定义方法,该方法主要用于拉取附件,查看其它9个数组,都是调用该方法. 可以判断,内存溢出是由拉取附件导致。 由于10个数组的内存都一样,我猜测,可能是拉取同一封邮件的附件一直拉取不完,然后到数据库查有哪些邮件需要拉取附件但是附件未拉取到,定位到相应的邮件,而且该邮件的附件有180多M,和溢出对象匹配,这样就查出原因了。为什么有10个数组内存都这么大,我们这边有个逻辑是如果其他服务请求邮件服务某封邮件附件拉取不到会重新请求再拉取(设置超时时间为20分钟),然而邮件服务还在一直从第三方邮件服务器拉取附件,如果有10个请求过来了,就会有10个特别大的byte数组用于读取附件内容。

转载于:https://my.oschina.net/beanGo/blog/3038073