问题描述
使用JProfiler进行性能测试时发现如下情况: 在程式不停的运行中,query.list分配的内存不会被回收。不断创建新的instance. 是多线程运行的程序。 使用Query的方法如下: public List find(String strhql) { // TODO Auto-generated method stub List result = null; Session session = null; Query query = null; try { session = this.getSession(); session.beginTransaction(); query = session.createQuery(strhql); result = query.list(); session.getTransaction().commit(); session.flush(); session.clear(); session.close(); } catch (Exception e) { session.getTransaction().rollback(); logger.debug("执行数据库中查询时失败,语句为:" + strhql, e); } finally { query = null; this.closeSession(session); } return result; } 有没有遇到过这种情况的朋友,有可行的解决方法么? 问题补充:<div class="quote_title">javahero1984 写道</div><div class="quote_div">query.list(); 分配了新的内存地址 result是对这个内存的引用,能否回收是要看你的result的引用以及外层对result的引用什么时候消除,仔细检查一下,如果最外层的引用消除就能回收内存了。这不是hibernate的错。</div><br /><br /><br />在该释放result应用的地方,我都已经释放掉,但是对于org.hibernate.Query.list的内存依然没有被释放掉
解决方案
木有2级缓存我觉得可能就变2个了检查下你HibernateSessionFactory的构造方法,如果每次都是config之后new一个,那你就用完直接把sessionFactory也关了然后看下你Impl包里面的THDservice,是不是有什么方法没有if做判断一直叫getParam()
解决方案二:
朋友,你这个问题解决了吗,我都快愁死了!
解决方案三:
引用没有用Spring大哥你也变通下嘛,hibernate配置扔出来看下啊hibernate的 list()不释放,我个人觉得是它返回了proxy 相当于iterator方法给你的延时加载,然后等你调用它但实际上你已经把需要的结果实例化给了result (result你null不null都不重要,你flush不flush也不用要,clear不clear也不重要,只要你close了就行)关闭session后 这个proxy并不会释放,因为放在2级缓存里了好了,再次session,因为list()方法查询一级缓存后就直接找数据库了压根不会找2级,你每次List result = query.list() 就会创一个proxy但这个proxy完全不会被用到,也没有释放另外要说的是,Hibernate 的list()default设置是不会返回proxy的所以要看你配置文件 ! 明白?
解决方案四:
session = this.getSession(); 你用这种方法打开session,显然是让spring帮你管理了你自己close不close都不会理你,而且你每次null一个Session肯定新建一个instance啊。。。贴你的配置文件
解决方案五:
在你取出list.get(0)后手动设置result=null
解决方案六:
List results = CollectionHelper.EMPTY_LIST;public static final List EMPTY_LIST = Collections.unmodifiableList( new ArrayList(0) );这是Hibernate里的源码,调用Query.list都会产生一个新的ArrayList,这是你没法控制的,除非你想要修改它,不过我觉得没有这样的必要,因为我想这在于你的程序的设计,多线程,你还希望Query.list返回单例,不太明白你的意图是?而且你所说的内存消耗过大的问题,我不觉得这真实存在,很多项目里面我都使用这个,但没有什么问题发生。
解决方案七:
query.list(); 分配了新的内存地址 result是对这个内存的引用,能否回收是要看你的result的引用以及外层对result的引用什么时候消除,仔细检查一下,如果最外层的引用消除就能回收内存了。这不是hibernate的错。