背景:JavaWeb项目部署在Tomcat服务器上,服务器用的Windows。
问题表现:系统出现偶发性无法访问(隔几天就会在早上无法访问)
Tomcat的日志catalina中,有如下报错信息。
java.lang.OutOfMemoryError: GC overhead limit exceeded
通过查询资料,显示该错误表示 Java 虚拟机(JVM)花费了大量时间进行垃圾回收(GC),但回收的内存却很少,达到了一个限制,从而抛出该异常。这通常意味着应用程序存在内存泄漏或者内存使用效率极低的问题。
问题排查过程:
一开始通过重启Tomcat解决这个问题,后来隔一段时间就会出现这种情况,发现不对劲,此时意识到问题的严重性。
开始排查这个问题,因为项目中有定时任务,每天凌晨2点会执行。想到的是不是这个定时程序中内存出现了泄漏,没有及时关闭文件流或者链接什么的。
沿着这个思路,开始看定时任务每天执行的日志。
发现有个定时任务的日志,只有开始日志,没有看到结束的日志。
推测程序应该是在执行这个定时任务的过程中出现了问题,开始逐步调试这个任务的代码,这个任务的主要工作是把本地的文件转成pdf格式的文件,然后调用第三方接口,把pdf文件传输给对方。
通过代码调试,发现程序走到这个方法的时候,进程会卡死在这里,不会继续往下走,即使等待了很久也不会继续执行代码,基本上定位到问题发生的地方了。
这个方法是把ppt格式文件转为pdf格式文件。
执行save方法时,如果文件有10M大小,那么就会卡死这这个地方。
解决问题:
又查了一下资料,可以通过改变Tomcat内存的大小来解决,下面是一些建议:
因为服务器上的Tomcat是以服务的形式安装的,找到Tomcat配置页面:
最大内存根据实际情况来配置即可。
修改完点击应用,确定,再重启Tomcat服务器。
问题解决啦!