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

来源:互联网 发布:淘宝直通车下载 编辑:程序博客网 时间:2024/05/17 20:12

原文文章地址:点击打开链接

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

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

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

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

 

疑点一:

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

主要代码:

public void run()     {        System.out.println("PoolManager 开始:"+this.hashCode());        this.setPriority(Thread.MAX_PRIORITY);        while(true)        {        System.out.println("连接池管理---");            try            {                sleep(FRESH_TIME);            }            catch(Exception e)            {                   e.printStackTrace();            }            Iterator iterator = ConnectionMap.conMap.keySet().iterator();             while (iterator.hasNext())             {                ConnectionPool pool = ConnectionMap.conMap.get(iterator.next());             //pool.            pool.remove();            }        }    }

分析:

    Iterator iterator;
    ConnectionPool pool;

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

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

 

疑点二:

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

分析:

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

ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");

 初次使用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,在自定义监听中,执行 

ServletContext context = event.getServletContext();ApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(context);Sys.ctx=ctx;
action中直接取用Sys.ctx。注意,自定义监听必须在监听器org.springframework.web.context.ContextLoaderListener
之后。
 
      问题:不确定是否有线程冲突,目前自测情况暂无问题,如有问题,后续处理

0 0