tomcat内存溢出各种问题处理以及JVM调优

tomcat内存溢出各种问题处理以及JVM调优

  • 服务器Tomcat内存溢出的原因
    • Java代码导致OutOfMemoryError错误
    • java.lang.OutOfMemoryError: PermGen space异常处理
    • java.lang.OutOfMemoryError: Java heap space异常处理
    • java.lang.OutOfMemoryError: GC overhead limit exceeded异常处理

服务器Tomcat内存溢出的原因

生产环境中Tomcat内存设置不好很容易出现内存溢出。造成内存溢出是不一样的,当然处理方式也不一样。在自己编写代码的时候需要考虑使用占用内存等尽可能优化。

Java代码导致OutOfMemoryError错误

需要重点排查以下几点:

  1. 检查代码中是否有死循环或递归调用。
  2. 检查是否有大循环重复产生新对象实体。
  3. 检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
  4. 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

java.lang.OutOfMemoryError: PermGen space异常处理

原因:
PermGen space的全称是Permanent Generation 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)那么就会产生此错误信息了。
但目前的hibernate和spring项目中也很容易出现这样的问题。可能是由于这些框架会动态class,而且jvm的gc是不会清理PemGen space的,超过了jvm默认的大小(4M),导致内存溢出。

解决方案:
设置MaxPermSize大小修改
1.linux系统下 TOMCAT_HOME/bin/catalina.sh在

echo "Using CATALINA_BASE:   $CATALINA_BASE"

上面加入以下行:

JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m

2.Windows系统下 TOMCAT_HOME/bin/catalina.bat在
在catalina.bat的第一行增加:

set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

java.lang.OutOfMemoryError: Java heap space异常处理

原因:
Java heap space,Java应用程序创建的对象存放在这片区域,垃圾回收(Garbage Collection)也发生在这块区域。通常一些比较“重型”的操作可能会导致该异常,比如:需要创建大量的对象,层次比较深的递归操作等。
解决方案有两种,一是优化应用,找到消耗大量内存的地方,然后优化代码或者算法。这种方式比较推荐,但是难度比较大,尤其是在产品环境中出现这种问题,开发人员不能很好的重现问题。第二种方案是提升Java heap size,这种方式虽然感觉有点治标不治本,但是可行性非常高,操作简单。
解决方案:
1.Windows系统下 TOMCAT_HOME/bin/catalina.bat在

 set MAINCLASS=org.apache.catalina.startup.Bootstrap
 set ACTION=start
 set SECURITY_POLICY_FILE=
 set DEBUG_OPTS=
 set JPDA=

下添加如下一行:

set CATALINA_OPTS=-Xms512m   -Xmx512m

java.lang.OutOfMemoryError: GC overhead limit exceeded异常处理

原因:
GC占用了多余98%(默认值)的CPU时间却只回收了少于2%(默认值)的堆空间。目的是为了让应用终止,给开发者机会去诊断问题。一般是应用程序在有限的内存上创建了大量的临时对象或者弱引用对象,从而导致该异常。虽然加大内存可以暂时解决这个问题,但是还是强烈建议去优化代码,后者更加有效。
解决方案:
首先,你可以关闭JVM这个默认的策略: java -XX:-UseGCOverheadLimit JavaApp
其次,你也可以尝试去加大Heap Size:java -Xmx512m JavaApp

你可能感兴趣的:(tomcat)