2011-03-24 78 views
3

任何人都可以說我的應用程序有什麼問題嗎?休眠:OutOfMemoryError:PermGen空間

public class HibernateUtil { 
    private static final SessionFactory sessionFactory; 

    static { 
     try { 
      sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); 
     } catch (Throwable ex) { 
      System.err.println("Initial SessionFactory creation failed." + ex); 
      throw new ExceptionInInitializerError(ex); 
     } 
    } 

    public static SessionFactory getSessionFactory() { 
     return sessionFactory; 
    } 
} 

public boolean insertUser(User user) { 
    Session session = HibernateUtil.getSessionFactory().openSession(); 
    try { 
     session.beginTransaction(); 
     session.save(user); 
     session.getTransaction().commit(); 

    } catch (HibernateException he) { 
     session.getTransaction().rollback(); 
     return false; 
    }finally{ 
     if (session != null){ 
      session.close(); 
     } 
    } 

    return true; 
} 

這是唯一的方法,我稱之爲插入數據庫中的用戶,然後如果我嘗試插入另一個,推出此異常:

Initial SessionFactory creation failed.java.lang.OutOfMemoryError: PermGen space 

更新: 我不知道hibernate.cfg中是否有內容,但是在這裏:

<?xml version="1.0" encoding="UTF-8"?> 

org.hibernate.dialect.MySQLDialect com.mysql.jdbc.Driver 的jdbc:mysql的://本地主機:3306/XXXXX XXXX XXXXc 線程

<!-- Connection pool C3P0 --> 
    <property name="hibernate.c3p0.acquire_increment">2</property> 
    <property name="hibernate.c3p0.min_size">5</property> 
    <property name="hibernate.c3p0.max_size">100</property> 
    <property name="hibernate.c3p0.timeout">20</property> 
    <property name="hibernate.c3p0.max_statements">50</property> 
    <property name="hibernate.c3p0.idle_test_period">60</property> 

    <!-- To show sql output on the screen --> 
    <property name="hibernate.show_sql">true</property> 
    <property name="hibernate.format_sql">true</property> 

    <!-- Mapping the tables in my schema --> 
    ... 

</session-factory> 

爲什麼出現這種情況以及如何解決它?

此致敬禮, 瓦爾特恩裏克。

+0

你說的意思是「嘗試插入另一個」?如果你在同一個JVM中執行它,爲什麼靜態初始化器會再次執行? – axtavt 2011-03-24 11:37:05

+0

@axtavt當我嘗試在我的數據庫中插入另一個用戶時,我的意思是。 – 2011-03-24 11:38:33

+0

@Valter:你從NetBeans開始吧?你有沒有嘗試創建一個'war'文件並將其部署到單獨的Tomcat安裝中? – axtavt 2011-03-24 12:00:31

回答

2

您可以增加永久生成大小,您應該添加-XX:MaxPermSize=128m作爲jvm選項。但它真的很奇怪,默認perm世代大小不足以爲您的程序。

+0

我覺得太奇怪了,我的場景是tomcat 6(最新版本)+ netbeans 6.9.1 + hibernate。 – 2011-03-24 11:40:11

+0

你是否嘗試增加maxpermsize?.. – 2011-03-24 11:43:23

+0

我現在改變了,我按照這個教程: http://www.mkyong.com/tomcat/tomcat-javalangoutofmemoryerror-permgen-space/,但即使我改變了大小,這個錯誤不會再發生? – 2011-03-24 11:47:31

4

「java.lang.OutOfMemoryError:PermGen空間」異常的最常見的根本原因是由反覆熱載入更改觸發的存儲泄漏一個web容器。

  • 您是否從NetBeans熱載入您的Web容器?

  • 如果重新啓動Web容器,問題「消失」嗎?

如果兩個問題的答案都是「是」,那麼這可能是您的問題。

有三種解決方案:

  • 不要熱負荷。或者至少要更頻繁地重新啓動Web容器。

  • 增加使用-XX:MaxPermSize=...

  • 追查和解決什麼實際導致存儲泄漏PermGen的堆限制。

有一個陰蒂泄漏綜合徵,發生在熱負荷。保留對使用某個熱載類的舊版本創建的一個對象實例的引用將泄漏全部由class classloader加載的類以及它們的所有靜態。


據@Daniel,休眠產生大量代理類,這將使用PermGen的空間,可以保證增加PermGen的堆大小。我預計這會穩定下來;即「熱身」的應用程序不會再生成任何代理類。但是,可能是熱加載導致熱身重複發生,並且代理類如上泄漏。

+0

您好斯蒂芬,這是我的情況,對您的問題是,我會做更多的重新啓動,我已經增加了我的-xx:MaxPermSize,我會盡力追查是什麼讓這個存儲泄漏。 謝謝。 – 2011-03-24 15:37:50

7

Hibernate和大型項目很常見。 PermGen是類存儲的地方(這不是堆!)。現在每個班都進入PermGen,如果項目足夠大,64MB的默認大小已經不夠了。

Hibernate爲您的實體即時生成代理類。這可能是你在Hibernate環境中出現這個錯誤的原因。生成的類也可能填充PermGen。

一般建議:如果它不是一個玩具項目,只需增加您的PermGen -XX:MaxPermSize=96M,您可以安全一段時間。

另請注意,Web應用程序容器在卸載應用程序時可能會出於多種原因(服務器端的log4j配置是一個常見問題),並且所有的Hibernates生成的類都將一次又一次地通過webapp創建。在這種情況下更好地重新啓動服務器

+0

現在,我更瞭解發生了什麼,感謝您的評論丹尼爾。 – 2011-03-24 15:36:01

+0

我認爲proxyclasses是我最後的原因,謝謝。 – 2017-04-03 11:56:35

5

我之前就遇到過這個問題,發現它是由於數據庫連接池C3PO中以前的內存泄漏而導致的,該數據庫連接沒有正確關閉。

因此,解決方案是在卸載servlet上下文時手動硬重置並關閉C3PO數據源。

因此,在自定義的ServletContextListener,添加以下代碼contextDestroyed(...)方法:

Set<PooledDataSource> pooledDataSourceSet = (Set<PooledDataSource>) C3P0Registry.getPooledDataSources(); 

    for (PooledDataSource dataSource : pooledDataSourceSet) { 
     try { 
      dataSource.hardReset(); 
      dataSource.close(); 
     } catch (SQLException e) { 
      // note - do not use log4j since it may have been unloaded by this point 
      System.out.println("Unable to hard reset and close data source.", e); 
     } 
    }