Tomcat中的Out Of Memory错误

本文详细解析了Tomcat中常见的内存溢出错误,包括PermGenspace和Javaheapspace错误的原因及解决方法,并提供了具体的配置修改示例。
 

tomcat中的outofmemory错误

1、PermGen space错误

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域Out Of Memory Error: PermGen space

从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。

改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

2、在tomcat中redeploy时出现outofmemory的错误.

可以有以下几个方面的原因:

1)     使用了proxool,因为proxool内部包含了一个老版本的cglib.

2)     log4j,最好不用,只用common-logging

3)     老版本的cglib,快点更新到最新版。

4)     更新到最新的hibernate3.2

 

3、这里以tomcat环境为例,其它WEB服务器如jboss,weblogic等是同一个道理

 

一、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)那么就会产生此错误信息了。

解决方法: 手动设置MaxPermSize大小

修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以达到减少jar 文档重复占用内存的目的。

二、java.lang.OutOfMemoryError: Java heap space
Heap size 设置
JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,
其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。

提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。

提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。

解决方法:手动设置Heap size

修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE:   $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -Xms800m -Xmx800m   -XX:MaxNewSize=256m"

三、实例,以下给出1G内存环境下java jvm 的参数设置参考:

JAVA_OPTS="-server -Xms800m -Xmx800m  -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "


三、相关资料

/show/3/7/20061112220131.htm

/show/3/7/20061112220054.htm

/show/3/7/20061112220201.htm

题外话:经常看到网友抱怨tomcat的性能不如...,不稳定等,其实根据笔者几年的经验,从"互联星空“到现在的房产门户网,我们
均使用tomcat作为WEB服务器,每天访问量百万多,tomcat仍然运行良好。建议大家有问题多从自己程序入手,多看看java的DOC文档
并详细了解JVM的知识。这样开发的程序才会健壮。

延伸阅读:

JVM 性能调整的一些基本概念

apache+Tomcat负载平衡设置详解[转]

java - the Java application launcher

JVM调优[转]

 

<think>我们正在处理一个关于JVM Metaspace内存溢出的问题。用户遇到了`java.lang.OutOfMemoryError:Metaspace`错误,需要故障排除和解决方案。根据引用[4]:Metaspace是Java8及以上版本中用于存储类元数据的主存储器,它替代了之前的PermGen空间,并且使用本地内存(NativeMemory)。因此,当Metaspace内存不足时,就会抛出OutOfMemoryError。可能的原因:1.应用程序加载了过多的类,超出了Metaspace的默认大小。2.存在类加载器泄漏(特别是自定义类加载器),导致已加载的类无法被卸载,从而使得Metaspace中的类元数据不断增长。3.动态生成类(例如使用字节码操作库如ASM、CGLIB等)过多,且生成的类没有被及时回收。解决方案:1.调整Metaspace的大小:通过JVM参数设置最大Metaspace大小,例如:`-XX:MaxMetaspaceSize=256m`。这可以防止Metaspace无限制地增长。2.监控Metaspace的使用情况:使用工具(如JVisualVM、JConsole、JMC等)监控Metaspace的使用,观察其增长趋势。3.检查类加载器泄漏:使用堆转储(heapdump)分析工具(如Eclipse MAT)分析类加载器的数量,查看是否有自定义类加载器没有被回收。4.减少动态类的生成:如果应用使用了大量动态代理(如Spring AOP、Hibernate等),考虑减少不必要的代理生成,或者调整缓存策略。5.启用Metaspace的垃圾回收:Metaspace的垃圾回收是自动进行的,但是可以通过参数`-XX:+MetaspaceSize`设置初始大小,并设置`-XX:MetaspaceSize`的初始值(例如`-XX:MetaspaceSize=64m`)以避免频繁调整大小带来的性能开销。6.升级JDK版本:有时,新版本的JDK可能优化了Metaspace的管理,因此升级到最新版本可能有助于解决问题。根据引用[2]和[3]:我们可以使用Java分析工具(如JProfiler、VisualVM)来监控内存使用情况,并记录GC活动。另外,引用[5]提到了设置合理的超时时间以避免线程阻塞,但这个问题与Metaspace溢出没有直接关系,不过整体性能优化也是需要考虑的。具体步骤建议:1.首先,通过设置`-XX:MaxMetaspaceSize`来限制Metaspace的最大大小,避免占用过多系统内存。2.然后,使用监控工具观察Metaspace的使用情况,如果发现使用量持续增长,则可能存在类加载器泄漏。3.获取堆转储文件,分析类加载器和类的数量。重点检查是否有重复加载的类,或者自定义类加载器是否被正确回收。4.如果应用使用了动态生成类的框架,检查框架的配置,例如CGLIB的缓存设置(可以尝试使用`-Dcglib.useCache=true`,但实际上默认是开启缓存的,所以可能需要调整缓存大小或减少代理类的生成)。注意:在Java8中,Metaspace的默认最大大小是受系统可用内存限制的,也就是说,它可能会一直增长直到耗尽系统内存。因此,设置`MaxMetaspaceSize`是必要的。另外,如果应用有大量的类加载(例如动态语言支持、OSGi容器等),可能需要更大的Metaspace,因此调整大小是第一步。如果问题依然存在,则需要深入分析类加载的情况。生成相关问题:1.如何监控JVM的Metaspace使用情况?2.如何分析类加载器泄漏?3.如何设置JVM参数以优化Metaspace?4.动态生成类(如使用CGLIB)如何导致Metaspace溢出?5. Metaspace和PermGen空间有什么区别?</think>### JVM Metaspace内存溢出问题分析与解决 当JVM抛出`java.lang.OutOfMemoryError: Metaspace`错误时,表明存储类元数据的Metaspace区域已耗尽。以下是系统化的故障排查与解决方案: #### **原因分析** 1. **类加载器泄漏** 自定义类加载器(如OSGi、热部署框架)未正确卸载,导致已加载类的元数据无法回收[^4]。 2. **元数据过量增长** - 动态生成大量代理类(如Spring AOP使用CGLIB) - 框架频繁反射生成类($JAXB$、$Hibernate$) - 应用服务器热部署次数过多 3. **配置不当** - Metaspace默认无上限(仅受物理内存限制) - 未设置`-XX:MaxMetaspaceSize`参数 4. **第三方库问题** 某些库(如旧版ASM字节码库)可能产生冗余类元数据[^1]。 #### **解决方案** 1. **调整JVM参数** ```bash -XX:MaxMetaspaceSize=256m # 设置Metaspace上限 -XX:MetaspaceSize=64m # 初始大小触发GC阈值 -XX:+UseG1GC # G1垃圾回收器优化元数据回收 ``` 2. **监控与诊断** - 使用$JVisualVM$或$JMC$监控Metaspace使用趋势 - 添加GC日志分析: ```bash -Xlog:gc*,gc+metaspace*=trace:file=gc_meta.log ``` - 通过堆转储分析类加载器: ```bash jmap -dump:format=b,file=heapdump.hprof <pid> ``` 在Eclipse MAT中检查`ClassLoader`对象数量[^2]。 3. **代码级修复** - 检查自定义类加载器的`close()`逻辑,确保卸载资源 - 限制动态代理生成(如Spring配置`proxyTargetClass=false`) - 减少反射操作,尤其是`Method.invoke()`高频调用[^1] 4. **框架优化** - 热部署环境(如Tomcat)调低`reloadable`频率 - 升级到JDK 11+,利用[元数据分层压缩](https://openjdk.org/jeps/8251152) #### **预防措施** ```mermaid graph LR A[监控] --> B[设置Metaspace警报阈值] B --> C[定期GC日志分析] C --> D[压力测试验证配置] D --> E[类加载器泄漏检测] ``` #### **工具推荐** | 工具 | 用途 | |------|------| | JDK Mission Control | 实时元数据监控 | | Eclipse MAT | 分析堆转储中的类加载器 | | GCMV | 可视化GC暂停与内存分配[^2] | > **关键提示**:从JDK 8开始,Metaspace取代PermGen使用本地内存,其溢出通常与类加载器生命周期管理直接相关[^4]。生产环境建议部署APM工具(如Dynatrace)实现自动化监控[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值