drools内存泄露问题排查分析

[b]一、现象[/b]
某系统使用了drools规则引擎对用户数据按照规则进行计算,在对其某查询接口连续100W次调用过程中发现JVM内存可用量持续下降,从系统启动时的1.5G下降为20-30M,导致java.lang.OutOfMemoryError: Java heap space只能被迫重启系统。
[b]二、排查[/b]
根据问题现象初步判定为系统出现内存泄露,但系统中使用了众多变量,如何判断是哪些变量没有被GC及时回收而导致内存泄露的呢?接下来开始寻找JVM内存监控工具。jprofiler是一个不错的选择(不过是收费软件)。找到crack,最初试图在RedHat Enterprise Linux AS release4上安装但是失败。不过可以在本地eclipse上安装jprofiler插件对内存变量进行监控分析。启动本地系统后(-Xms512M -Xmx512M),jprofiler同时启动。对本地服务连续进行10W次调用同时通过jprofiler对变量进行监控发现drools规则引擎中的部分变量占用内存量排名靠前(org.drools.*),通过jprofiler的GC强制回收功能也无法释放内存占用量,内存创建大量实例。当调用数为926次时报java.lang.OutOfMemoryError: Java heap space,内存占用量如下图:

[img]http://dl.iteye.com/upload/attachment/180038/17554fde-2e3b-3f1b-82e0-74f7212901f4.jpg[/img]

google一下,[url]http://hi.baidu.com/funshare/blog/item/d2f4a8c3006c545db219a84c.html[/url]。
于是按照上面的解决方案修改drools规则计算部分代码。
修改后第926次调用时jprofiler监控结果如下图:
[img]http://dl.iteye.com/upload/attachment/179792/63a89e3b-529a-366a-83aa-cda2b764c783.jpg[/img]
已经没有drools大量占用内存情况出现了。初步确定了问题原因。
其实jconsole也是一个很好的监控工具,并且由jdk自带。这次使用jconsole对远程服务器上的应用进行监控。
drools计算规则代码修改前3小时时间段内堆内存占用量如下图:
[img]http://dl.iteye.com/upload/attachment/179795/7efcbc1d-7800-3cd2-8cdf-39f5f9609a47.jpg[/img]
内存占用量呈持续上升趋势。
修改后3小时时间段内堆内存占用量如下图:
[img]http://dl.iteye.com/upload/attachment/179799/cdd82f4b-a7f7-38c6-8ea4-2f675d44daa9.jpg[/img]
可以看到内存占用量比较平稳。堆内存总占用量也有所下降。问题可以得到确认。
[b]三、经验[/b]
通过解决该问题获得了一些经验教训:
1、此类问题需要通过工具长时间的持续跟踪才能发现,1小时内通常不容易发现问题。
2、擅用google。

------------------------------------
GC回收机制的概念和原理:[url]http://rdc.taobao.com/blog/qa/?p=4708[/url]
JVM监控工具:[url]http://androider.iteye.com/blog/293814[/url]
JProfiler和Eclipse整合:[url]http://hi.baidu.com/dburu/blog/item/c397b644e3fde78ab3b7dc78.html[/url]
Jconsole使用:[url]http://rdc.taobao.com/blog/qa/?p=1261[/url]
JConsole使用手册:[url]http://hi.baidu.com/xuwanbest/blog/item/3f6d4c7b375ff4f10bd18731.html[/url]
利用JProfiler对应用服务器内存泄漏问题诊断一例:[url]http://yufeimen.iteye.com/blog/70721[/url]


vi /home/admin/test-run/bin/jbossctl.sh
JAVA_OPTS="$JAVA_OPTS -Dprogram.name=$PROGNAME -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false"

bash jbossctl.sh stop
bash jbossctl.sh start -b10.253.67.32

你可能感兴趣的:(java)