为啥会出现OutOfMemoryError
内存中加载的数据量过于庞大,如一次从数据库取出过多数据; 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
代码中存在死循环或循环产生过多重复的对象实体; 使用的第三方软件中的BUG; 启动参数内存值设定的过小;
OutOfMemoryError几种情况
最常见的有这3种
java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: GC overhead limit exceeded
(堆内存溢出)java.lang.OutOfMemoryError: Java heap space
Java heap space,Java应用程序创建的对象存放在这片区域,垃圾回收(Garbage Collection)也发生在这块区域。通常一些比较“重型”的操作可能会导致该异常,比如:需要创建大量的对象,层次比较深的递归操作等。
解决方案有两种,一是优化应用,找到消耗大量内存的地方,然后优化代码或者算法。这种方式比较推荐,但是难度比较大,尤其是在产品环境中出现这种问题,开发人员不能很好的重现问题。第二种方案是提升Java heap size,这种方式虽然感觉有点治标不治本,但是可行性非常高,操作简单。
如果是在tomcat中,出现的这种问题,解决办法是在{tomcat_dir}/bin/catalina.bat中找到如下几行:
在后面加上一行(数字根据自己的需要调整):
set CATALINA_OPTS=-Xms512m -Xmx512m
(方法区内存溢出)java.lang.OutOfMemoryError: PermGen space
Perm Gen Size(Permanent Generation Size),用来存储被加载的类的定义(class definition)和元数据(metadata),比如:Class Object和Method Object等。这是内存中的一块永久保存区域,JVM的垃圾回收不会触及这块区域。通常在加载一个非常大的项目的时候才会出现该异常。
如果是在tomcat中出现这个问题,解决办法是在{tomcat_dir}/bin/catalina.bat中添加如下一行:
set CATALINA_OPTS=-server -Xms256m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m
java.lang.OutOfMemoryError: GC overhead limit exceeded
这个错误会出现在这个场景中:GC占用了多余98%(默认值)的CPU时间却只回收了少于2%(默认值)的堆空间。目的是为了让应用终止,给开发者机会去诊断问题。一般是应用程序在有限的内存上创建了大量的临时对象或者弱引用对象,从而导致该异常。虽然加大内存可以暂时解决这个问题,但是还是强烈建议去优化代码,后者更加有效。
首先,你可以关闭JVM这个默认的策略:
1 java -XX:-UseGCOverheadLimit JavaApp
其次,你也可以尝试去加大Heap Size:
1 java -Xmx512m JavaApp
注意:在修改Tomcat的catalina.bat(*.sh)中的内容时,网上有很多都是说直接修改JAVA_OPTS,按照Apache官方的说法是:
Note: Do not use JAVA_OPTS to specify memory limits. You do not need much memory for a small process that is used to stop Tomcat. Those settings belong to CATALINA_OPTS.
预防OutOfMemoryError从我做起
导致java.lang.OutOfMemoryError的根本原因是程序不健壮
圈起来,这句话是重点
怎么做?
1、尽早释放无用对象的引用
2、使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域
3、尽量少用静态变量,因为静态变量存放在永久代(方法区),永久代基本不参与垃圾回收
4、避免在循环中创建对象
5、开启大型文件或从数据库一次拿了太多的数据很容易造成内存溢出,所以在这些地方要大概计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。
windows环境中直接到jdk安装目录bin文件夹下双击jvisualvm.exe打开,或者在cmd下输入jvisualvm回车。查看更多信息