首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2EE开发 >

hibernate中sessionfactory的封锁机制

2013-12-23 
hibernate中sessionfactory的关闭机制?我在java应用中使用hibernate连接数据库,不使用spring托管,遇到mysq

hibernate中sessionfactory的关闭机制?
我在java应用中使用hibernate连接数据库,不使用spring托管,遇到mysql超时自动断开问题。我百度了一下相关问题的解答,绝大部分是使用连接池,另外的解答是每次连接的时候都创建新的sessionfactory。

经过一天的大量实验,我现在有如下疑问:

在不使用连接池的情况下,也就是只用hibernate的默认连接池的情况下:

我每次数据库操作都创建新的sessionfactory对象,这个方法是能使用的。但是sessionfactory是重量级组件,每次创建非常占内存,因此我实验了一下,用一个for循环,创建3000个sessionfactory对象,发现果然内存直线上升,大概占用了200M左右的内存。我机器上的mysql最大连接数是100,当sessionfactory的数量超过mysql的最大连接时,后面创建的sessionfactory都无法进行数据库操作,但是依旧可以创建,并且占用大量内存。

代码如下:

public void test(){
Configuration cfg = new Configuration().configure();
ArrayList<SessionFactory> al = new ArrayList<SessionFactory>();

for (int i = 0; i < 3000; i++) {

SessionFactory sf = cfg.buildSessionFactory();
          


}


因此,我尝试在每一次创建sessionfactory后,再使用sessionfactory.close()方法将其立即关闭。如此尝试3000次循环后,连接不仅断开了,而且内存几乎没有增加,似乎是sessionfactory对象被回收了。

代码如下:
public void test(){
Configuration cfg = new Configuration().configure();
ArrayList<SessionFactory> al = new ArrayList<SessionFactory>();

for (int i = 0; i < 3000; i++) {
SessionFactory sf = cfg.buildSessionFactory();     
sf.close();
}


我的问题来了:

第一个问题,如果我将每次循环中的sessionfactory对象存入一个arraylist,之后调用了close()方法,连接虽然被断开,但是内存依旧明显增加,也就是似乎sessionfactory对象没有被回收,依旧占用内存。这是为什么呢?是存入arraylist中,系统就不会回收了么?

代码如下:
public void test(){
Configuration cfg = new Configuration().configure();
ArrayList<SessionFactory> al = new ArrayList<SessionFactory>();
for (int i = 0; i < 3000; i++) {
SessionFactory sf = cfg.buildSessionFactory();
            sf.close();
            al.add(sf);
}


第二个问题,如果我在close()之后,再打印出sessionfactory对象的内存地址,依旧可以显示,但是内存没有增加,连接也断开了,似乎是sessionfactory对象被回收了,但是那样为什么还能打印出sessionfactory对象的内存地址呢?

代码如下:
public void test(){
Configuration cfg = new Configuration().configure();
ArrayList<SessionFactory> al = new ArrayList<SessionFactory>();

for (int i = 0; i < 3000; i++) {

SessionFactory sf = cfg.buildSessionFactory();
            sf.close();
           
            System.out.println(i+":"+sf);            
       



}


第三个问题,这个sessionfactory的close()方法,究竟谁是销毁对象,还是单单断开连接?如果是销毁对象,为什么还能读出它的内存地址呢?如果只是断开连接,为什么内存不会增加呢?
[解决办法]
java回收机制是在对象没有被引用的时候就回收,而且回收不是即时发生的。是每隔一段时间java自动扫描后回收的。所以如果你一直创建对象,而不close的话,内存肯定会上升,close()方法你可以理解为销毁对象,但不是真正的销毁,只是做到让java回收机制可以回收这个对象而已。
但是如果你创建之后放到list中,然后close(),虽然你close()了,但是很明显你的对象被引用了,所以java回收机制不会回收你的对象。
你创建对象之后,然后使用close()。理论上来说这个对象会被销毁,所以不具备内存地址,但是之前说过java回收机制不是即时的,所以你在close()之后打印肯定是有地址的

以上只是个人观点,不代表正确答案,谢谢!

热点排行