Hibernate:OutOfMemoryError:PermGen空间

时间:2011-03-24 11:23:04

标签: java hibernate exception out-of-memory

有谁能说我的申请有什么问题?

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>

为什么会发生这种情况以及如何解决?

祝你好运, Valter Henrique。

4 个答案:

答案 0 :(得分:7)

Hibernate和大型项目非常常见。 PermGen是存储类的地方(这不是堆!)。现在每个类都进入PermGen,如果项目很大,则不再需要64MB的默认大小。

Hibernate为您的实体动态生成代理类。这可能是您在Hibernate环境中出现此错误的原因。生成的类也可能填充PermGen。

一般建议:如果它不是玩具项目,只需使用-XX:MaxPermSize=96M增加您的PermGen,您就可以安全了一段时间。

请注意,Web应用程序容器可能由于多种原因而无法卸载应用程序(服务器范围的log4j配置是一个常见问题),并且将根据webapp一次又一次地创建所有Hibernates生成的类。在这种情况下,最好重新启动服务器。

答案 1 :(得分: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);
        }
    }

答案 2 :(得分:4)

“java.lang.OutOfMemoryError:PermGen space”异常的最常见根本原因是通过反复将热更改加载到Web容器中而触发的存储泄漏。

  • 您是否已从NetBeans将更改加载到Web容器中?

  • 如果重新启动网络容器,问题会“消失”吗?

如果两个问题的答案都是“是”,则可能是这是你的问题。

有三种解决方案:

  • 不要热负荷。或者至少更频繁地重新启动Web容器。

  • 使用-XX:MaxPermSize=...

  • 增加permgen堆的限制
  • 追踪并修复实际导致存储泄漏的任何内容。

热负荷会发生阴险的泄漏综合症。保留对使用旧版本的某个热载类创建的一个对象实例的引用将泄漏由类类加载器加载的所有类及其所有静态类。


根据@Daniel的说法,Hibernate生成了很多代理类,并且会使用permgen空间,并且可以保证增加permgen堆大小。我希望这会稳定下来;即,已经“预热”的应用程序将不再生成任何代理类。但是,热负载可能导致热重复发生,代理类如上所述泄漏。

答案 3 :(得分:2)

您可以增加永久代的大小,您应该将-XX:MaxPermSize=128m添加为jvm选项。但是真的很奇怪,默认的烫发生成大小对你的程序来说还不够。