主要有3种比较常见的OutOfMemory Error:
Java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: PermGen space
java.lang.OutOfMemoryError: GC overhead limit exceeded
1. java.lang.OutOfMemoryError: Java heap space
Java heap space,Java应用程序创建的对象存放在这片区域,垃圾回收(Garbage Collection)也发生在这块区域。通常一些比较“重型”的操作可能会导致该异常,比如:需要创建大量的对象,层次比较深的递归操作等。
解决方案有两种,一是优化应用,找到消耗大量内存的地方,然后优化代码或者算法。这种方式比较推荐,但是难度比较大,尤其是在产品环境中出现这种问题,开发人员不能很好的重现问题。第二种方案是提升Java heap size,这种方式虽然感觉有点治标不治本,但是可行性非常高,操作简单。
对于一般的应用,采用如下方式即可(数字根据自己的需要调整),解决办法:
“JVM 堆空间溢出(java.lang.OutOfMemoryError: Java heap space)”错误是JVM 堆空间不足,此时只需要调整-Xms 和-Xmx 这两个参数即可。
linux中在{tomcat_dir}/bin/catalina.sh :
export JAVA_OPTS="-Xms512m -Xmx2048m -Xss1024K -XX:PermSize=512m -XX:MaxPermSize=512m"
export CATALINA_OPTS="-Xms512m -Xmx2048m -Xss1024K -XX:PermSize=512m -XX:MaxPermSize=512m"
windows在{tomcat_dir}/bin/catalina.bat中找到如下几行:
set JAVA_OPTS=-server -Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m
set CATALINA_OPTS=-server -Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m
2. java.lang.OutOfMemoryError: PermGen space
”永久存储区溢出 PermGen space的全称是Permanent Generation space“ 或“(java.lang.OutOfMemoryError:Java Permanent Space)”,都是指内存的永久保存区域,乃是永久存储区设置太小,不能满足系统需要的大小,此时只需要调整-XX:PermSize 和-XX:MaxPermSize 这两个参数即可。
“PermGen space”这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中, 它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误, 这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。
解决办法:
linux在在{tomcat_dir}/bin/catalina.sh:
export JAVA_OPTS="-Xms512m -Xmx2048m -Xss1024K -XX:PermSize=512m -XX:MaxPermSize=512m"
export CATALINA_OPTS="-Xms512m -Xmx2048m -Xss1024K -XX:PermSize=512m -XX:MaxPermSize=512m"
windows在{tomcat_dir}/bin/catalina.bat中添加如下一行:
set JAVA_OPTS=-server -Xms256m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m
set CATALINA_OPTS=-server -Xms256m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m
3. java.lang.OutOfMemoryError: GC overhead limit exceeded
这个错误会出现在这个场景中:GC占用了多余98%(默认值)的CPU时间却只回收了少于2%(默认值)的堆空间。目的是为了让应用终止,给开发者机会去诊断问题。一般是应用程序在有限的内存上创建了大量的临时对象或者弱引用对象,从而导致该异常。虽然加大内存可以暂时解决这个问题,但是还是强烈建议去优化代码,后者更加有效。
4. CATALINA_OPTS和JAVA_OPTS区别
有两个环境变量 - CATALINA_OPTS和JAVA_OPTS- 都用于Tomcat 的catalina.sh启动和关闭脚本。它们在该文件中的注释中描述为:
[JAVA_OPTS] :(可选)执行“start”,“stop”或“run”命令时使用的Java运行时选项
[CATALINA_OPTS] :(可选)执行“start”或“run”命令时使用的Java运行时选项
那么为什么有两个不同的变量呢?有什么区别?
首先,在EITHER变量中指定的任何内容都以相同的方式传递给启动Tomcat的命令 - “start”或“run”命令 - 但只有在JAVA_OPTS中设置的值才会传递给“stop”命令。这可能对Tomcat在实践中的运行方式没有任何影响,因为它只影响运行的结束,而不是开始。
第二个区别更微妙。其他应用程序也可以使用JAVA_OPTS,但只有Tomcat才会使用CATALINA_OPTS。因此,如果您设置的环境变量仅供Tomcat使用,那么最好建议您使用CATALINA_OPTS,而如果您正在设置环境变量以供其他Java应用程序使用,例如JBoss,您应该放置您在JAVA_OPTS中的设置。