java调用dll内存溢出_Tomcat内存溢出 - Alex_Java的个人空间 - OSCHINA - 中文开源技术交流社区...

一、java.lang.OutOfMemoryError: Java heap space

中文:堆内存溢出

出现原因:Java应用程序创建的对象存在于堆中,垃圾回收(Garbage Collection,GC)也发生在这块区域。当大量产生Java对象时,或者层次比较深的递归等操作时会出现这个问题。

解决方案:

1.比较推荐去优化消耗内存的代码,设计更好的算法;但是难度比较大。

2.提升Java Heap Size,虽然治标不治本,但可行性高。

Linux环境: TOMCAT_HOME/bin/catalina.sh

在echo "Using CATALINA_BASE:$CATALINA_BASE"上面加入以下行:

JAVA_OPTS="$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m"

Windows环境:TOMCAT_HOME/bin/catalina.bat

在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:

set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m

二、java.lang.OutOfMemoryError:PermGen Space

中文:永久区内存溢出

分析:这一部分存放class和meta的信息,class在被加载的时候被放入PermGen Space区域,它和存放Instance(实例)的Heap(堆)区不同,GC不会在主程序运行期堆PermGen Space进行清理,所以程序会加载很多类的时候,就很有可能会出现PermGen错误。这种错误常见在Web服务器对JSP进行Pre Compile(预编译)的时候,如果Web app下用了大量的第三方jar,其大小超过jvm设置的大小时,就会产生此错误信息。

原因:

1)内存中加载的数量过于庞大,如一次从数据库中取出过多数据;

2)集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;

3)代码中存在死循环或循环产生过多的对象实体;

4)使用第三方软件中的bug;

5)启动参数内存值设定得过小。

解决方案:

Linux环境: TOMCAT_HOME/bin/catalina.sh

在echo "Using CATALINA_BASE:$CATALINA_BASE"上面加入以下行:

JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxNewSize=256M -XX:MaxPermSize=256M"

Windows环境:TOMCAT_HOME/bin/catalina.bat

在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:

set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=256M

参数说明:

-Xms:JVM初始分配的堆内存,生产环境建议与Xmx相同,设为1024M以上。

-Xmx:JVM最大允许分配的堆内存,生产环境建议设为1024M以上

-Xss:线程堆栈大小,JDK5以上一般设置为256K或以上

-XX:PermSize:JVM初始分配的非堆内存,不会被回收,生产环境建议与MaxPermSize相同,设为256M以上。

-XX:MaxNewSize:JVM堆区域新生代内存的最大可分配大小,生产环境建议设为800M~1024M

-XXMaxPermSize:JVM最大允许分配的非堆内存,生产环境建议设置为256M以上。

更多参数参见我转载的文章:Tomcat启动参数

三、OutOfMemoryError:unable to create new native thread

中文:无法创建新的线程

这种现象比较少见,主要和JVM与系统内存的比例有关。

这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。有人发现,在线程个数很多的情况下,你分配给JVM的内存越多,那上述错误发生的可能性越高。

产生原因:

每个32位的进程最多可以使用2G的可用内存,因为另外2G被操作系统保留。这里假设1.5G给JVM,那么还剩500M给可用内存。这500M内存中的一部分必须用于系统dll的加载,那么真正剩下的也许只有400M。

现在关键的地方出现了:当你使用Java创建一个线程,在JVM的内存里也会创建一个Thread对象,但同时也会在操作系统里创建一个真正的物理线程(参考JVM规范)。操作系统会在余下的400M内存里创建这个物理线程,而不是在JVM的1500M的内存堆里创建。在JDK1.4里,默认的栈大小是256KB,但是在JDK1.5里,默认的栈大小时1M/线程。因此在余下400M的可用内存里边,我们最多也只能创建400个可用线程。

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

给出一个有关能够创建线程的最大个数的估算公式:

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

对于jdk1.5而言,假设操作系统dll加载保留120M内存:

1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads

1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads

在2000/XP/2003的boot.ini里头有一个启动选项,好像是:/PAE /3G ,可以让用户进程最大内存扩充至3G,这时操作系统只能占用最多1G的虚存。那样应该可以让JVM创建更多的线程。

因此:我们需要结合不同情况对tomcat内存分配进行不同的诊断才能从根本上解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值