java.lang.OutOfMemoryError: Java heap space内存溢出问题解决实战

     Tomcat提示错误为:java.lang.OutOfMemoryError: Java heap space,出现这个问题时从表面来看是属于内存溢出,去到现场环境时CPU的使用率为99%,内存容量还剩三分之一(8G内存的PC),初始想法是tomcat给JVM的内存空间分配少了,打开catalina.bat文件,发现分配的内存空间为1G,应该也不算小,后询问开发人员,提到此内存溢出的情况发生过多次,之前的处理方式一直为重启服务器,且一般在重启的第三天系统出现问题(内存溢出),所以推测为项目中应该有一些地方在new对象之后没有将连接进行关闭,导致GC无法清理有连接但未被使用的对象,又根据服务器重启(内存清除)之后三天就发生溢出,推测可能代码中存在死循环,通过检查代码证实以上推测正确,如图所示:

java.lang.OutOfMemoryError: Java heap space内存溢出问题解决实战

(方法名aaa为自己在notepad++随便写的),从上述代码可以可以看出List<Message>对象一直在循环中被创建,在被使用时里面的数据也没有被清空,由于此处无限循环,且该方法在项目启动时被初始化调用,所以该方法一直未被结束,也就是说创建的无数个List<Message>都未和方法aaa断开连接,导致GC认为这么多List<Message>都是可用资源(附:关于GC对于局部变量的清理的大概机制:一个对象在被new或者被引用到时会和new或者引用的方法建立一个连接,此连接在new这个对象所属的方法结束时断开与此对象的所有连接,当GC在一定时间判断该对象没有连接的时候才会将其清除),所以导致JVM的堆空间一直不断增长,所以导致后内存溢出的问题;

总结:代码中用到的多线程(尤其是终身循环的那种)没有释放局部变量的连接,导致JVM(java虚拟机)不能及时清理heap(堆)中不使用了的对象导致JVM堆内存溢出;

此异常发生需要检查以下几个地方:

1、查看JVM的运行内存空间,适当的提高运行内存空间;

2、检查项目中的代码是否存在死循环,如果存在检查是否做好了资源的清理;

3、检查项目中是否存在一次性提取大量数据到内存的地方(10万数据以上);

(如有问题,请评论指教,谢谢!)