struts2+spring+hibernate小项目内存溢出解决过程

本文介绍了在struts2+spring+hibernate项目中遇到的内存溢出问题,详细分析了数据库连接池管理模块导致的内存增长以及BaseAction类中的ApplicationContext引起的内存占用。通过调整代码,将循环内的局部变量移出,并使用静态变量存储ApplicationContext,有效解决了内存溢出问题。同时提出了可能存在的线程冲突风险及后续处理方案。

测试目标:公司的struts2+spring+hibernate项目

测试环境:JDK1.5.0、TOMCAT5.5、SqlServer2000

测试原因:系统运行时发现内存不断增加,操作到达一定次数后PermGen space的outmemory错误。

测试工具:Jprofilter5.2.1检测内存情况

 

疑点一:

数据库连接池管理模块中有一个线程,运行期定期执行,检测池中连接状态。此线程每运行一次,内存增加5K-2M不等

主要代码:

分析:

    Iterator iterator;
    ConnectionPool pool;

    两个对象在循环中,每次循环声明一次,造成每次申请一个新内存空间,使内存数量增加。但此内存空间可被gc释放,不是内存溢出的原因。

解决:以上两变量声明提到循环外

 

疑点二:

      项目中所有action每执行一次,消耗内存若干,且不释放,所有action均继承自定义的BaseAction类,估计是BaseAction的问题。

分析:

      写脚本单独运行BaseAction,并逐个去除其成员,最终确定造成内存溢出的是BaseAction的一个成员。

      初次使用SSH框架,前期未作深入学习,只知道FileSystemXmlApplicationContext由spring提供,可用以创建ApplicationContext实例,而ApplicationContext实例可用于hibernate对象的创建,具体原理不明。

      测试发现FileSystemXmlApplicationContext每生成一次,applicationContext.xml文件中配置的bean全部创建一次实例,估计是为注入做准备用,但使用完后,内存空间不释放,原因不明,猜测是spring内部机制。不过既然每次执行全部bean都被创建,估计此方法应该是为spring框架整体运行做准备使用的,而不是针对具体操作使用的,用在此处就不太合适了。

      网上搜了一下,web应用中,spring提供了一个监听器org.springframework.web.context.ContextLoaderListener,用以初始化ApplicationContext对象,此对象实例贯穿项目运行始终,可使用WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);获得。

      但ApplicationContext ctx 是BaseAction成员,创建BaseAction时ServletContext 尚未赋值,ServletContext sc为空,因此ctx无法获得对象。

最终解决:

      增加静态变量Sys.ctx,在自定义监听中,执行

 

      action中直接取用Sys.ctx。注意,自定义监听必须在监听器org.springframework.web.context.ContextLoaderListener

之后。

 

      问题:不确定是否有线程冲突,目前自测情况暂无问题,如有问题,后续处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值