3

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.

Daniel
  • 27,718
  • 20
  • 89
  • 133
Valter Silva
  • 16,446
  • 52
  • 137
  • 218
  • What do you mean by "try to insert another one"? If you do it in the same JVM, why static initializer is execute again? – axtavt Mar 24 '11 at 11:37
  • @axtavt When i try to insert another user in my database, i mean. – Valter Silva Mar 24 '11 at 11:38
  • @Valter: You start it from NetBeans, right? Have you tried to create a `war` file and deploy it into separate installation of Tomcat? – axtavt Mar 24 '11 at 12:00
  • @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. – Valter Silva Mar 24 '11 at 12:05
  • @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. – axtavt Mar 24 '11 at 12:32
  • @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? – Valter Silva Mar 24 '11 at 15:40
  • @Valter: Sorry, I'm not familiar with NetBeans. – axtavt Mar 24 '11 at 15:44

4 Answers4

7

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.

Daniel
  • 27,718
  • 20
  • 89
  • 133
5

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);
        }
    }
Nicholas Hemley
  • 339
  • 4
  • 5
4

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 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. – Valter Silva Mar 24 '11 at 15:37
2

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

Gursel Koca
  • 20,940
  • 2
  • 24
  • 34