tomcat内存溢出的三种情况说明

  tomcat的内存溢出的本质其实就是JVM内存溢出,所以我们先了解以下javaJVM有关的内存知识。

  JVM管理两种类型的内存,堆和非堆,堆是给开发人员用的,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放ClassMeta信息的。它和堆不同,GC不会在主程序运行期对这块内存空间进行清理。

  (1) 堆内存设置

    JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置。JVM的初始空间(即-Xms)默认是物理内存的1/64JVM最大空间(即-Xmx)默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。

    因此一般情况下设置-Xms-Xmx相等以避免在每次GC 后调整堆的大小。可以利用JVM提供的-Xmn -Xms -Xmx等选项进行堆内存设置,一般的要将-Xms-Xmx选项设置为相同,而-Xmn1/4-Xmx值,堆的最大值设置不要超过可用物理内存的80%

  (2) 非堆内存PermGen space(全称Permanent Generation space)

    也称为永久保存的区域,用于存放ClassMeta信息,Class在被Load的时候被放入该区域。它和存放类实例(Instance)Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理。JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4GC不会对PermGen space进行清理,所以如果加载很多的Class的话,就很有可能出现PermGen space的错误。


以下我们针对tomcat内存溢出的三种情况做说明:


  1. OutOfMemoryErrorJava heap space 堆溢出

    这种情况属于JVM堆溢出,在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候就会抛出此异常。


  2. OutOfMemoryErrorPermGen space 非堆溢出

    这种错误常见于:

      (1) web服务器对JSP进行编译的时候;

      (2) 使用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)

      (3) 项目应用有太多的class文件而恰好MaxPermSize设置较小;

      (4) tomcat热部署时侯不清理前面加载的环境,只将context更改为新部署的时候。


  3. OutOfMemoryErrorunable to create new native thread. 无法创建新的线程

    这种现象比较少见,也比较奇怪,主要是和jvm与系统内存的比例有关。

    具体的原因分析:每一个32位的进程最多可以使用2G的可用内存,因为另外2G被操作系统保留。这里假设使用1.5GJVM,那么还余下500M可用内存。这500M内存中的一部分必须用于系统dll的加载,那么真正剩下的也许只有400M,现在关键的地方出现了:当你使用Java创建一个线程,在JVM的内存里也会创建一个Thread对象,但是同时也会在操作系统里创建一个真正的物理线程(参考JVM规范),操作系统会在余下的400兆内存里创建这个物理线程,而不是在JVM1500M的内存堆里创建。在jdk1.4里头,默认的栈大小是256KB,但是在jdk1.5里头,默认的栈大小为1M每线程,因此,在余下400M的可用内存里边我们最多也只能创建400个可用线程。

    这样结论就出来了,要想创建更多的线程,就需要调整分配给JVM的最大内存。还有一种做法是让JVM宿主在你的JNI代码里边。


下面总结一下javaJVM内存配置项:

-Xmx Java Heap最大值,默认值为物理内存的1/4


-Xms Java Heap初始值,ServerJVM最好将-Xms-Xmx设为相同值;


-Xmn Java Heap Young区的值;


-Xss 每个线程的Stack值;


-XX:PermSize:设定内存的永久保存区域;


-XX:MaxPermSize:设定最大内存的永久保存区域;


-XX:NewSize:设置JVM堆的新生代的默认值;


-XX:MaxNewSize:设置JVM堆的新生代的最大值;

 

 

一些参考配置方案:

1. 这种配置方案是我在eclipse集成tomcat做开发的时候使用的:

-Xms1024m -Xmx1024m -Xmn256m -XX:PermSize=256M -XX:MaxPermSize=512m


2. 这种配置方案是我在linux环境中配置tomcat的时候使用的:

在bin文件夹下面创建文件setenv.sh,并保存以下内容:

[root@localhost bin]# vim setenv.sh
<!-- setenv.sh内容开始,其实就是声明环境变量 -->
#!/bin/sh
#Program:
#   set tomcat environment variables.
#History:
#   2016/09/29 wy
                                                                                                                           
JAVA_OPTS="-Xms1024m -Xmx1024m -Xmn256m"
JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m"

<!-- 保存以上内容到setenv.sh文件中 --> [root@localhost bin]
# chmod -R 755 setenv.sh  <!-- 更改setenv.sh权限,设置为可执行 -->

 

posted on 2016-05-05 10:49  一路东逝  阅读(334)  评论(0编辑  收藏  举报

导航