OutOfMemory

问题描述
在采购中心、劳动局、人民日报社、新闻总署等项目中都出现了内存溢出而系统崩溃的现象。以采购中心为例,在并发用户数不超过5人情况下,

运行一天左右系统就会出现OutOfMemory异常,进而导致JBoss服务停止。

背景知识
JVM的内存管理
从1.4.2开始,为了减少垃圾回收的消耗,jvm开始使用基于generation的回收机制。与Java对象的生命周期对应,JVM的内存分成了三个

generation:Young,Tenured、Perm三种。其中Young又包括Eden和两个survivor区,如下图所示:

新的Java对象通常放置在Young的Eden区域,很多一次性的Java对象会很快的在小垃圾回收的时候被释放掉。对于生命周期比较长的对象,在survivor之间多次复制之后,

就会被放置到Tenured区域中去。所以tenured区域(也叫old区域)存放的是长生命周期的Java对象。而在Perm空间中存放的则是Java class信息(包括class与相应的

metadata数据、编译的JSP等)以及采用String.intern方法产生的字符串实例。

以往调优过程中,我们通过使用-Xmx参数调整的heap size实际上是Young + Tenured区域的最大空间,并不包括Perm空间。下图是采购中心项目中的内存使用情况:

从这个图中,我们可以看出,heap size为256m(实际上我们使用了-Xmx256m参数),Perm generation的最大值为128m,目前仅分配了68m,其余的60m为vitural,

并没有实际分配。

什么是OutOfMemory?
我们在项目中见到的内存溢出异常,就是一个简单的OutOfMemoryError信息。你无法知道到底是哪里出现了内存溢出,也无法获取该内存溢出的详细信息,进而给问题定位

带来极大的困难。如下面所示:

2007-03-05 17:19:10,703 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/myapp].[jsp]] Servlet.service() for servlet jsp threw exception
java.lang.OutOfMemoryError
在使用j2sdk1.4.2的后续版本中对于OutOfMemoryError进行了丰富,给出了更具体的异常信息。除了最常见的java heap space之外,在测试中还出现了permgen full和out of swap space的类型。实际上这几种类型都和上面提到的jvm内存管理机制有关。

Java heap space
这种类型的内存溢出是我们最熟悉的,对应的内存区域是Young+Tenured。当应用中消耗的内存超出时,垃圾回收会发生的很频繁,系统会变得很慢。当垃圾回收时间所占比重

过大,而且也没有多余的空间可以分配的时候,那么系统就会出现内存溢出错误。

这种内存溢出错误一般包括两种原因:

应用的瞬间内存消耗过大,特别是在并发情况下。当压力降低后,还可以通过垃圾回收来释放内存,并不会导致系统的崩溃。在系统运行过程中,这种情况很少,即使存在,也可以通过修改-Xmx来进行解决。[如果设置到1G左右的空间,对于]
系统中存在着内存泄露情况,此时系统将无法使用。必须要修改应用,排除错误。
Permgen full
上面说过,Perm空间主要是用于存储java class信息(也包括编译后的JSP)以及通过String.intern生成的字符串等。默认情况下,在jdk1.4.2中该空间的最大值为64M。如果系统中class数量很大时,就有可能造成Perm空间不足,从而导致系统崩溃。

out of swap space
在系统监控过程中出现过一次,这个错误信息实际上是指系统物理内存不足。此时如果通过-Xmx来调高内存反而会更糟,因为可用的空余物理内存更低了。所以此时应该降低Java Heap Size。

原因分析
将jdk更新成1.4.2_13之后运行系统,很快我们可以发现系统出现permgen full错误。在本次测试中,主要监控了各个模块对于Perm空间的消耗情况;为了防止系统中出现内存泄露等heap space错误,同时也监控各个模块对于heap space空间消耗的情况。

单用户下监测结果
测试模块 Perm空间(M) Perm空间变化(M) 垃圾回收之后Heap空间(M) Heap空间变化
JBoss启动 36.243 - 47 -
登陆和导航 37.256 1.013 49 2
Galaxy管理模块 47.15 9.9 76 17
公文系统 48.7 1.55 78 2
公文统计 66.737 18.037 89 11
资料管理 71.07 4.34 96 7
并发多用户下监测结果
测试模块 Perm空间 Perm空间变化 垃圾回收之后的Heap空间(M) Heap空间变化
JBoss启动 37.175 - 68.1 -
登陆和导航 41.142 3.97 74.32 6.2
Galaxy管理模块 42.339 1.2 80.53 4.2
公文 46.941 4.6 88.31 7.8
公文统计 56.118 9.2 95.61 7.3
资料管理 64.388 8.2 86.25 -9.4
结果分析
Perm空间变化
通过使用jstat、visualgc等工具监控之后,分析Perm空间增长的主要原因如下:

有些组件有自己的ClassLoader,所以在使用相关模块之后,会继续Load很多类进入到perm空间。比如BIRT,会load很多class出来,从而导致perm空间快速增加。

由于采用了spring、Ibatis等,相应Bean的生成和方法调用采用反射机制,所以在perm里面除了相应的bean类等,还会出现临时的一些反射类。

应用中同时存在大量的jsp页面,当jsp编译之后也会进入perm空间

在jstl和el中也大量使用了反射机制,所以也会在Perm空间中增加一些临时性的反射类,如com.sun.reflect.GenericConstructor287等。

从上面的分析中可以看出,当系统中的所有Class或者JSP等都已经Load到Perm空间之后,Perm空间的大小基本上就保持稳定了。只是在访问jsp等情况下生成的反射类会临时增加空间的大小,这些临时的类过段时间之后会unload,从而释放出相应的空间。

在测试过程中,Perm最大空间基本上维持在了73m左右。

Heap空间变化
在测试过程中并没有发现有内存泄露的现象。虽然在垃圾回收之后Heap空间仍然在上升,这主要是由于Galaxy、Spring、Ibatis等都采用了Cache机制。进而导致内存的增大。特别是Galaxy的Cache初始设置时间为24小时,所以在测试过程中基本上不会被释放。在并发多用户测试环境下,将其修改为10分钟,当运行资料管理的时候明显看到了heap空间的减少。

结论
在采购中心项目与GOA中存在Perm空间不足的问题,该问题可以通过修改系统配置进行解决。
系统中不存在Heap空间内存泄露的现象。
人员与组织结构管理、公文统计存在CPU消耗过大,导致这两个模块并发情况下无法使用。具体原因还需要进一步排查。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值