2015-05-14 111 views
1

我在Tomcat 7上運行的Java Web應用程序 - jdk1.7休眠java.lang.OutOfMemoryError:Java堆空間

該應用使用Spring 4.1.5.RELEASE和Hibernate 4.2.2.Final

我的問題是堆空間的建設部分廠房

一個OutOfMemoryException異常這是我打開一個SessionFactory

public class GenericDAO { 

    public static SessionFactory sessionFactory = null; 
    public static ServiceRegistry serviceRegistry = null; 

    Transaction tx = null; 

    public static SessionFactory createSessionFactory() { 
     Configuration configuration = new Configuration(); 
     configuration.configure(); 
     serviceRegistry = new ServiceRegistryBuilder().applySettings(
      configuration.getProperties()). buildServiceRegistry(); 
     sessionFactory = configuration.buildSessionFactory(serviceRegistry); 
     return sessionFactory; 
    } 
} 

靜態方法,這是一個例子Ø ˚FDAO

public class SpecificDAO extends GenericDAO { 
    public int save(MyObject item) { 
     Session session = createSessionFactory().openSession(); 
     try { 
      tx = session.beginTransaction(); 
      session.save(item); 
      tx.commit(); 
      return item.getId(); 
     } catch (HibernateException e) { 
      if (tx != null) tx.rollback(); 
       e.printStackTrace(); 
     } finally { 
      session.close(); 
     } 
     return -1; 
    } 
} 

在含有

的sessionFactory = configuration.buildSessionFactory(serviceRegistry)的線路中發生的誤差;

不會立即出現在部署問題,但經過使用

2 O 3天內是我的hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC 
    "-//Hibernate/Hibernate Configuration DTD//EN" 
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
<session-factory> 
    <property name="connection.url">jdbc:sqlserver://192.168.XX.XXX:1433;databaseName=DatabaseName</property> 
    <property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property> 
    <property name="connection.username">username</property> 
    <property name="connection.password">password</property> 
    <mapping class="it.company.client.project.hibernate.MyObject"/> 

    <!-- DB schema will be updated if needed --> 
    <!-- <property name="hbm2ddl.auto">update</property> --> 
</session-factory> 
</hibernate-configuration> 
+1

燦你顯示你的hibernate.cfg.xml? – Kiki

+2

爲什麼在每次save()調用時創建SessionFactory?你可以只實例化一次並重用。 – StanislavL

+0

我敢打賭你的程序不是很快。 – user1516873

回答

1

這是更好的主意,沖洗和清除會話中使用後,您可以同時使用

session.flush(); 
session.clear(); 

瞭解更多信息link1link2

1

您正在創建每次保存()調用一個SessionFactory對象。

即要創建一個新的SessionFactory反覆每次保存()調用,但在內存中不關閉現有的SessionFactory對象。

多少次保存()被調用? SessionFactory的相同號碼將在內存中,這會導致內存泄漏。

的SessionFactory是重量級的對象,所以你會在應用程序初始化創建。您可以創建一個SingleTon來實例化SessionFactory。

2

你只有一次創建會話工廠,因爲它是一個沉重的重物,請參閱hibernate documentation其細節。

下面是從文檔示例代碼上應該如何創建:在每個DAO動作SessionFactory對象的

import org.hibernate.SessionFactory; 
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 
import org.hibernate.cfg.Configuration; 

public class HibernateUtil { 

    private static final SessionFactory sessionFactory = buildSessionFactory(); 

    private static SessionFactory buildSessionFactory() { 
     try { 
      // Create the SessionFactory from hibernate.cfg.xml 
      return new Configuration().configure().buildSessionFactory(
       new StandardServiceRegistryBuilder().build()); 
     } 
     catch (Throwable ex) { 
      // Make sure you log the exception, as it might be swallowed 
      System.err.println("Initial SessionFactory creation failed." + ex); 
      throw new ExceptionInInitializerError(ex); 
     } 
    } 

    public static SessionFactory getSessionFactory() { 
     return sessionFactory; 
    } 

} 
0

避免實例化。這是很慢並導致內存泄漏。如果您使用Spring反正不如授人以與SessionFactory對象,交易Spring工作和處理SQL例外this answer

更好地解釋。例如,您的save()方法將減少代碼sessionFactory.getCurrentSession().save(item);手動打開事務的一行/提交/回滾應該@Transactional屬性所取代。此外,通常在整個服務方法上更好的地方交易,而不是每個單獨的DAO方法,但它取決於業務邏輯。

Here例如如何配置與Hibernate(對於谷歌只是第一篇文章)工作Spring上下文

我微微通過這個例子對於當前問題

@Repository 
public class SpecificDAO { 
    private SessionFactory sessionFactory; 

    @Autowired 
    public SpecificDAO(SessionFactory sessionFactory) { 
     this.sessionFactory = sessionFactory; 
    } 

    @Transactional(propagation=Propagation.REQUIRED) 
    public int save(MyObject item) { 
     try{ 
      sessionFactory.getCurrentSession().save(item); 
     }catch (HibernateException e) { 
      return -1; 
     } 
    } 
} 

Spring配置

<context:annotation-config/> 
<context:component-scan base-package="it.company.client.project"/> 
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/> 
    <property name="url" value="jdbc:sqlserver://192.168.XX.XXX:1433;databaseName=DatabaseName"/> 
    <property name="username" value="username"/> 
    <property name="password" value="password"/> 
</bean> 
<bean id="sessionFactory" 
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="annotatedClasses"> 
      <list> 
       <value>it.company.client.project.hibernate.MyObject</value> 
      </list> 
     </property> 

     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop> 
       <prop key="hibernate.connection.provider_class">org.hibernate.connection.DatasourceConnectionProvider</prop> 
       <prop key="hibernate.show_sql">false</prop> 
       <!--prop key="hibernate.hbm2ddl.auto">update</prop--> 
      </props> 
     </property> 
</bean> 
<tx:annotation-driven /> 
<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 
相關問題