2016年7月20日星期三

Java_028: Heap Dump 分析报告:MemorySessionData 对象过多导致 OutOfMemoryError

环境:MAC OS X 10.11.5 + Oracle JDK 1.7.0_80 + MAT 1.6.0

客户运行的WebLogic 频繁报告 OutOfMemoryError,在应用服务器再次挂起之后,收集了当时的 Heap Dump。以下是 Heap Dump 分析报告。

1. Heap 使用概况
已知分配给 JVM 的 Heap 最大值为 4 G,从下图可以看出,已经使用的 Heap 大小总共为 3.6 G,最大对象为 31.1 M。
鼠标指向深色的对象,发现该对象是 weblogic.servlet.internal.session.MemorySessionData。


2. 怀疑的有内存泄露的对象
从下图可以看出,有 7716 个 weblogic.servlet.internal.session.MemorySessionData 实例对象, 总共占了 3,611,539,432 (94.39%) 字节,大约 3.6 G。


3. 怀疑的有内存泄露的对象
从下图可以看出,有大量“活着的” weblogic.servlet.internal.session.MemorySessionData 实例对象。


4. 按照 java 对象个数和占用大小排序查看
从下图可以看出,蓝色选中的对象,是有严重嫌疑的对象,实例数量多,且占空间大,在 1G~3G 之间不等。

按照 MemorySessionData 过滤,发现确实有 7716 个该对象占了 3,611,539,432 (94.39%) 字节,大约 3.6 G的内存空间。

5. 进一步查看 weblogic.servlet.internal.session.MemorySessionData 引用的对象大小
从下图可以看出,经过层层查找,最终锁定对象 psft.pt8.util.PSSessionProp 对象。
开始怀疑每个 MemorySessionData 大对象中都包含一个 psft.pt8.util.PSSessionProp 大对象。

按照 psft.pt8.util.PSSessionProp 过滤,发现确实有 7716 个该对象占了 3,591,220,008 字节,大约 3.59 G的内存空间。而且,7716 这个数字和 MemorySessionData 的数量一样。
说明确实每个 MemorySessionData 大对象中都包含一个 psft.pt8.util.PSSessionProp 大对象。

6. 结论
当客户登陆系统后,会自动生成一个 weblogic.servlet.internal.session.MemorySessionData 对象,由于每个 weblogic.servlet.internal.session.MemorySessionData 对象中,都被放入了一个 psft.pt8.util.PSSessionProp 大对象(大小为 32 M)。一共有 7716 个 MemorySessionData 和 PSSessionProp 对象,导致内存几乎被占满,并最终导致 OutOfMemoryError。

建议如下:
(1)检查代码中,使用 psft.pt8.util.PSSessionProp 的地方。
(2)检查代码中,是否有死循环或递归调用。
(3)检查代码中,是否有大循环重复产生新对象实体。
(4)检查代码中,是否使用了 List、MAP等集合对象后没有清除,List、MAP 等集合对象会始终存有对对象的引用,使得这些对象不能被 GC 回收。
(5)修改 web.xml,把 session 过期时间适当调低,默认是半个小时。
<session-config>
     <session-timeout>30000</session-timeout>
</session-config>

参考文献:
1. http://www.voidcn.com/blog/guogang83/article/p-5979082.html
2. http://www.cnblogs.com/cyjch/archive/2012/04/10/2440421.html