Hibernate :OutOfMemoryError: PermGen space

14,569

Solution 1

Very common with Hibernate and large project. The PermGen is the place where the classes are stored (this is not the Heap!). Every now class comes into PermGen, and if the project is large enought, the default size of 64MB is not enought anymore.

Hibernate generated Proxy classes for your entities on the fly. This might be a reason why you get this error in the context of Hibernate. The generated classes also might fill the PermGen.

General advice: If it is not a toy project, just increase your PermGen with -XX:MaxPermSize=96M and you are safe for a while.

Please also note that Web application containers might have problems unloading applications for several reasons (a server wide log4j configuration is a common problem), and all of Hibernates generated classes will be created again and again per webapp. Better restart your server in this case.

Solution 2

I have had this problem before and found it was caused by a previous memory leak in the database connection pooling C3PO, which is not shut-down correctly.

The solution, therefore, is to manually hard reset and close the C3PO data sources when the servlet context is undeployed.

So, in a custom ServletContextListener, add the following code in the contextDestroyed(...) method:

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);
        }
    }

Solution 3

The most common root cause of "java.lang.OutOfMemoryError: PermGen space" exceptions is storage leaks triggered by repeatedly hot-loading changes into a web container.

  • Have you been hot-loading changes into your web container from NetBeans?

  • Does the problem "go away" if you restart the web container?

If the answer to both questions is "yes" then the chances are that this is your problem.

There are three solutions:

  • Don't hot-load. Or at least do full restarts of your web container more often.

  • Increase the limit on the permgen heap using -XX:MaxPermSize=...

  • Track down and fix whatever is actually causing the storage leaks.

There is an insidious leak syndrome that occurs with hot-loading. Retaining a reference to one object instance created with the old version of some hot-loaded class will leak all classes loaded by the classes classloader, and all of their statics.


According to @Daniel, Hibernate generates a lot of proxy classes, and that would use permgen space, and could warrant increasing the permgen heap size. I'd expect this to stabilize; i.e. an application that has "warmed up" would not generate any more proxy classes. However, it could be that hot-loading is causing the warmup to happen repeatedly, and the proxy classes are leaking as above.

Solution 4

You could increase permanent generation size , you should add -XX:MaxPermSize=128m as jvm option. But it is really strange that default perm generation size is not enough for your program..

Share:
14,569
Valter Silva
Author by

Valter Silva

Updated on June 07, 2022

Comments

  • Valter Silva
    Valter Silva almost 2 years

    could anyone say what's wrong with my application?

    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;
    }
    

    This is the only method i call to insert an user in the database, and then if i try to insert another one, launch this exception:

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

    UPDATE: I don't know if there's something in hibernate.cfg but here it go:

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

    org.hibernate.dialect.MySQLDialect com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/XXXXX XXXX XXXXc thread

        <!-- 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>
    

    Why this happen and how to fix it ?

    Best regards, Valter Henrique.

    • axtavt
      axtavt about 13 years
      What do you mean by "try to insert another one"? If you do it in the same JVM, why static initializer is execute again?
    • Valter Silva
      Valter Silva about 13 years
      @axtavt When i try to insert another user in my database, i mean.
    • axtavt
      axtavt about 13 years
      @Valter: You start it from NetBeans, right? Have you tried to create a war file and deploy it into separate installation of Tomcat?
    • Valter Silva
      Valter Silva about 13 years
      @axtavt i did'n try that, because netbenas integrates with tomcat wich means is more productive, i mean, i code and netbeans deploy dinamically. But you think Netbeans is doing wrong the deploying ? I see some people talking about eclipse too. I think this is some issue in tomcat.. but this seems weird too me at all, cause, is a short application to give this kind of exception.
    • axtavt
      axtavt about 13 years
      @Valter: From your description it looks like static initializer of HibernateUtil is called twice. If so, it may be caused by some classloader-related magic, for example, used for hot redeploy. So, I think you need to try it at clean Tomcat without IDE.
    • Valter Silva
      Valter Silva about 13 years
      @axtavt, makes sense what you said, so doing this hot loading i what's causing this problem then.. there's another way to keeping doing the hot loading and don't launching this error?
    • axtavt
      axtavt about 13 years
      @Valter: Sorry, I'm not familiar with NetBeans.
  • Valter Silva
    Valter Silva about 13 years
    i think is weird too dude, my scenario is tomcat 6 (lastest version) + netbeans 6.9.1 + hibernate.
  • Gursel Koca
    Gursel Koca about 13 years
    did you try to increase maxpermsize ?..
  • Valter Silva
    Valter Silva about 13 years
    i change now, i follow this tutorial : mkyong.com/tomcat/tomcat-javalangoutofmemoryerror-permgen-sp‌​ace , but even if i change the size, this error will not happen again ?
  • Gursel Koca
    Gursel Koca about 13 years
    If you are starting tomcat from netbeans, you should make changes by using netbeans..
  • Valter Silva
    Valter Silva about 13 years
    Now i understand better what's happening, thanks by your comment Daniel.
  • Valter Silva
    Valter Silva about 13 years
    Hi Stephen, that's my case, yes to both your questions, i will do more restarts and i already increase my -xx:MaxPermSize and i will try to track down what is making this storage leak. Thanks.
  • Asad Khan
    Asad Khan about 7 years
    I think the proxyclasses is the reason at my end thanks.