关于struts和Tomcat7报告:Memory Leak 的问题。

  环境:struts2.2.1.1 + Spring3.05 + MyBatis + Tomcat7 。
现象:Tomcat每隔一段时间就报告Out Of Memeory Exception。 分析检查得知只要在tomcat7的管理端使用stop、reload就会导致memory leak。后台报错是:The web application [/XXXX] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10] (value [com.opensymphony.xwork2.inject.ContainerImpl$10@4a11a8]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@cd32e5]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 网上搜索都是什么CleanUp的问题,类似于:
<filter>
  <filter-name>struts-cleanup</filter-name>
  <filter-class>
   org.apache.struts2.dispatcher.ActionContextCleanUp
  </filter-class>
</filter>
<filter-mapping>
  <filter-name>struts-cleanup</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
结果都不灵。struts2官网上已经不推荐使用原始的filter了,改用什么prepareddispatchfilter以后就不需要增加上面的配置了。以为是工程的问题,从官网上下载demo,googlecode,嘿嘿嘿,严重警告,涛声依旧。

过程:开始还有其余几个类似的问题,都是由于使用Threadlocal而没有及时的清理掉导致的,重构代码就解决了。但是还有些问题,包括:The web application [/XXXX] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
从网上检索类似的问题都能够解决了。比如 JDBC driver的问题,可以使用一个listener,来监听application的结束事件,在事件中unregiste所有的驱动程序。由于系统用到了Spring的timer类,还出现了10个类似于以下的问题:
The web application [/XXXX] appears to have started a thread named [scheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak.都可以在listener中进行处理掉。但是最后剩下上面的那个问题无论如何怎么修改程序都不能去掉了。看样子也是由于使用 ThreadLocal变量导致的无法清理程序造成的。使用排除法,去掉部分代码,检查问题,依旧。去掉所有编写的代码,检查问题,依旧。这里两句话,实际上用了差不多两天。最终发现是struts2使用的xwork导致的问题。参见:https://issues.apache.org/jira/browse/WW-2167,号称解决了,其实呢。。。。就是ContainerImpl,反编译ContainerImpl$10.class得到一个threadlocal的实现。嘿嘿,下载源代码吧。修改源码,在
<T> T callInContext(ContextualCallable<T> callable) {
        Object[] reference = localContext.get();
        if (reference[0] == null) {
            reference[0] = new InternalContext(this);
            try {
                return callable.call((InternalContext) reference[0]);
            } finally {
                // Only remove the context if this call created it.
                reference[0] = null;
            }
        } else {
            // Someone else will clean up this context.                           PS:这个注释真真真。。。。。
            return callable.call((InternalContext) reference[0]);
        }
    }
方法中,增加try finally,在最后设置localcontext为空,看看结果:直接OutOfMemory,HeapSpace。。。。看来struts源码不是随便就可以改的啊!呵呵,没关系,还有招数,增加destroy方法,手动移除threadlocal变量,并设置该threadlocal为null,结果则么样??tomcat报错了,呵呵,在checkThreadLocalMap的时候,就直接空指针了。。。怎么办,那好,既然tomcat还要求必须检查该变量,OK,我只去除threadlocal中的内容,而不动threadlocal,总可以了吧。于是使用localcontex.remove()方法,这里还有个小插曲,本意是使用while循环,去掉localcontext中的所有内容,无奈死循环。。。哦,threadlocal,每thread只有一份,嘿嘿。基础知识不牢靠,靠。打包、发布,您猜怎么着,成功了!可是虽然后台不报告错误了,在tomcat7前台,findleak的时候,依然会有报告出来,我晕。后台不报错了都,哪里有leak??发现是spring 的quartz导致的,虽然我在 listener中对其进行了处理,但是在tomcat对他进行检查的时候,这个处理还没有进行。呵呵,不管。
最终方案: 使用修改过的xwork-core.jar,我命名为xwork-core2.2.9.1.jar以示与原来2.2.1.1的区别。放到maven上,嘿嘿大家用去吧。
下载地址: http://maven.marsorstudio.cn/org/apache/struts/xwork/xwork-core/2.2.9.1/
下载不了告诉我,到时候再确认吧,嘿嘿,懒一下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值