浏览 3266 次
|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2007-10-31 关键字: Spring iBatis Hessian
以前没有遇到过这种OOM,说奇怪是因为在Windows资源管理器中查看java进程的内存占用是正常情况,即增加和减少相持平。查看gc.log,Jprofiler进行跟踪调试,均正常,但是还是提示出现如下错误:
[16:52:20] java.lang.OutOfMemoryError: Java heap space [16:52:20] at com.rec.cell.common.ParseInputCommand.parseIdentPicCommand(ParseInputCommand.java:382) [16:52:20] at com.rec.cell.login.service.impl.IdentPicServiceImpl.identPicFvalue(IdentPicServiceImpl.java:97) [16:52:20] at sun.reflect.GeneratedMethodAccessor31.invoke(Unknown Source) [16:52:20] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [16:52:20] at java.lang.reflect.Method.invoke(Method.java:585) [16:52:20] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304) [16:52:20] at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172) 我的系统平台是 Win2003 Resin 3.12 Pro JDK 1.5 update 12 JVM配置参数为:
<jvm-arg>-server</jvm-arg>
<jvm-arg>-verbose:gc</jvm-arg>
<jvm-arg>-Xloggc:gc.log</jvm-arg>
<jvm-arg>-XX:+PrintGCDetails</jvm-arg>
<jvm-arg>-XX:+PrintGCTimeStamps</jvm-arg>
<jvm-arg>-noclassgc</jvm-arg>
<jvm-arg>-Xms512m</jvm-arg>
<jvm-arg>-Xmx512m</jvm-arg>
<jvm-arg>-XX:NewRatio=3</jvm-arg>
<jvm-arg>-XX:SurvivorRatio=8</jvm-arg>
<jvm-arg>-XX:PermSize=64m</jvm-arg>
<jvm-arg>-XX:MaxPermSize=128m</jvm-arg>
<jvm-arg>-Xss1m</jvm-arg>
Web系统组成为Spring 2.0+iBatis(DBCP)+Hessian,单线程跑此应用。 所以系统中大量使用了reflect功能,在初次运行时,过2分钟即出现如下错误: Unloading class sun.reflect.GeneratedMethodAccessor* 查找JVM配置,加上-noclassgc,使jvm不卸载加载的class,然后这个情况消失。因为系统中只有有限数量的class,并非网站类系统有n个jsp页面,所以-noclassgc加上是不会产生Permsize太小的错误的。 但是OOM的问题出现了 GC log如下: 4.865: [GC [PSYoungGen: 76702K->12689K(114688K)] 76702K->12689K(507904K), 0.0616025 secs] 4.927: [Full GC [PSYoungGen: 12689K->0K(114688K)] [PSOldGen: 0K->12622K(393216K)] 12689K->12622K(507904K) [PSPermGen: 10187K->10187K(65536K)], 0.0791577 secs] 8.925: [GC [PSYoungGen: 98304K->16371K(114688K)] 110926K->40147K(507904K), 0.1828853 secs] 42.080: [GC [PSYoungGen: 114675K->16377K(114688K)] 138451K->54191K(507904K), 0.0966398 secs] 106.919: [GC [PSYoungGen: 114681K->16381K(114688K)] 152495K->61151K(507904K), 0.0918806 secs] 206.359: [GC [PSYoungGen: 114685K->16371K(114688K)] 159455K->61141K(507904K), 0.0651641 secs] 312.719: [GC [PSYoungGen: 114675K->16374K(80256K)] 159445K->61144K(473472K), 0.0696641 secs] 380.916: [GC [PSYoungGen: 80246K->16409K(79936K)] 125016K->61179K(473152K), 0.0738506 secs] 446.445: [GC [PSYoungGen: 79866K->1819K(93824K)] 124636K->61326K(487040K), 0.0668315 secs] 512.122: [GC [PSYoungGen: 62683K->160K(60736K)] 122190K->61304K(453952K), 0.0301872 secs] 518.359: [GC [PSYoungGen: 6089K->139K(93120K)] 67234K->61288K(486336K), 0.0238365 secs] 518.383: [GC [PSYoungGen: 139K->123K(56704K)] 61288K->61308K(449920K), 0.0228543 secs] 518.406: [Full GC [PSYoungGen: 123K->0K(56704K)] [PSOldGen: 61184K->35359K(393216K)] 61308K->35359K(449920K) [PSPermGen: 20703K->20703K(65536K)], 0.1965706 secs] 518.602: [GC [PSYoungGen: 0K->0K(93760K)] 35359K->35359K(486976K), 0.0229942 secs] 518.625: [Full GC [PSYoungGen: 0K->0K(93760K)] [PSOldGen: 35359K->12463K(393216K)] 35359K->12463K(486976K) [PSPermGen: 20703K->20306K(65536K)], 0.1782066 secs] 用Jprofiler跟踪系统运行情况,入下图: Heap整体运行情况:
其中Eden区运行情况:
其中Old区运行情况:
其中Survivor区运行情况:
其中GC运行情况:
出现OOM的时间:就在最后一次Full Gc的时候 出现OOM的地点:语句为 new了一个76800大小的byte[],这条语句是在一个static函数里边的,在函数退出时理论上会被回收。 现象和疑问如下: 1.观察windows资源管理器。GC的log以及Jprofiler的图形显示,java内存以及本地内存并没有突然增加的迹象,一直保持在200M左右浮动。Resin的status页面显示的内存占用也是正常情况,为何在代码执行到此处时会出现OOm 2.新生代空间(PSYoungGen)一直在减小,从开始的100M左右减小到最后的60M左右。但是新生代的垃圾回收是正常的,从图中可以看出垃圾回收的过程和区总容量减小的过程。 3.Old区缓慢增加中,但是在最后一次gc的时候减小,old区容量并不大 4.Survivor区从一开始就一直处于Full的状态(全部被占用),但是当新生代空间减小的时候,Survivor区容量突然增加并且翻番,占用状况变的很小。在OOM的适合,此区容量变的接近于0 基于以上分析,尝试调整XX:SurvivorRatio=4,则OOM的出现时间更短。 实在是很疑惑,为什么会出现这种情况的OOM,以前遇见的都是系统内存飚升到web app出现OOM,但是现在外表看起来内存正常,但是发生OOM。请各位有经验的帮忙分析分析。 我查看资料,有说是因为jvm的原因导致内存碎片太多,致使分配大空间的时候不能连续分配从而引起OOM,不知道是不是这种原因。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2007-11-07
也许是pergemspace吧
|
|
| 返回顶楼 | |
|
最后更新时间:2007-11-01
static函数+static数组+reflect生成的类。
我不认为能在函数结束后释放。 能不能不用reflection,而用prototype之类的? 另外,楼上的,log 写的 heap space…… |
|
| 返回顶楼 | |
|
最后更新时间:2007-11-01
dwangel 写道 static函数+static数组+reflect生成的类。
我不认为能在函数结束后释放。 能不能不用reflection,而用prototype之类的? 另外,楼上的,log 写的 heap space…… 是通过spring暴露的hessian接口作为远程调用的入口函数A,然后这个入口函数A里边,调用的static函数进行一些功能性的解析,返回一个HashMap给A函数。其中new的那个byte[76800]就是加到HashMap里边返回给A函数的。也不是全都是static,至少数组不是。真的是不知道为啥会heap OOM了,一切显示都正常。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-11-07
无语
引用 Unloading class sun.reflect.GeneratedMethodAccessor*
是正常的现象,说明大量使用反射生成的class被jvm正确回收了。 看来你应该是permgen区outofmermory了,可以尝试在启动配置中加大permgensize,不过不建议太大,不要超过300M,而且这样也只能治标不能治本。 jdk dynamicproxy每次都会生成新的代理类,如果你不卸载这些代理类,permgen区outofmemory是迟早的事情。 如果你真的不想卸载加载到jvm中的代理类,就要考虑复用生成的代理,这样的话,jdk的dynamicproxy是不行的,你要使用cglib来生成可复用的代理类。 因此,你有两条路可以走 1、继续使用jdk的dynamicproxy,但不要禁止class卸载。 2、使用cglibproxy,复用代理类,避免大量生成的代理类。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-11-07
看上去不该是permgen的问题,因为permgen的OOM会明确的在异常中提示OutOfMemoryError: PermGen.
这个应该是普通的内存不足,如果不是内存太小(你配置了多少内存,给Resin的JVM设置的最大内存是多少?),那就很可能是你的代码在哪里没有释放引用的对象,比如存在一个全局性的容器类,不断的向里面加入对象,但没有删除的机制。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-11-16
我也遇到一个问题, 使用HashMap加载50w的词汇, 老是报
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 难道HashMap连50w都撑不上吗? 我是刚从.net转java的, 不熟悉, 望大家指点 |
|
| 返回顶楼 | |
|
最后更新时间:2007-11-16
因为默认heap space大小为64m, 所以当加载到20多w时刚好65m, 直接就报溢出了, 后来加上 -Xms300m -Xmx300m 参数, 顺利通过~
|
|
| 返回顶楼 | |
|
最后更新时间:2007-11-16
瞎碰:Xss不要设置,默认好像才2k,它对内存的占用是Xss×线程数量, gclog可以增加选项 -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution
|
|
| 返回顶楼 | |










