工作中虽然不经常遇到java.lang.OutOfMemoryError: Java heap space,但一旦出现将会严重影响系统运行,如果不能迅速解决,将会带来很恶劣的影响,所以掌握OutOfMemoryError:Java heap space的解决方法也是非常有必要的。
解决问题首先要找出原因,要找原因要有依据,而内存溢出时的堆dump信息是最为重要的依据之一
步骤一:先保证能拿到堆dump信息
我写了一个简单的小例子,jvm运行参数为:-Xmx20M -Xms20M -XX:+HeapDumpOnOutOfMemoryError
程序执行后很快就会抛出内存溢出错误
其实通过异常信息基本已经可以锁定内存溢出原因,但为了解决问题思路具有通用性,我们继续往下看
步骤二:分析堆内存溢出时的dump文件
堆dump文件可以直接下载我的dump文件,用Eclipse Memory Analyzer或者VisualVM打开,我用的是Eclipse Memory Analyzer
可以看到这两个线程占的内存总量达到了近90%
再进一步展开Thread-2的堆信息
可以看到有大量的byte数组,就是我们代码中新建的数组,正是因为这个原因导致内存溢出。当然在实际业务代码中能看到具体的业务类名称,基本上就一目了然了。
步骤三:如果堆dump信息也正常怎么办?
可能经过上面两个步骤的分析,虽然确实由于堆中对象太多导致内存溢出,但都是正常的对象,没有某个类的对象产生特别多的情况,应该怎么办?
这时候就考虑增大堆内存的大小,或者减少对象的产生
方法1:直接增加堆内存大小,调整-Xmx -Xms 的大小
方法2:本地缓存改为集中缓存。大量使用本地缓存(如大量使用HashMap作为K/V缓存),会占用堆上很多内存,尤其在集群情况下,会造成更多浪费,这时可以考虑把本地缓存改为集中缓存(如Redis)。
方法3:考虑优化代码,看是否有优化的空间。