【问题标题】:Hibernate :OutOfMemoryError: PermGen space [duplicate]休眠:OutOfMemoryError:PermGen 空间 [重复]
【发布时间】:2011-07-22 01:23:50
【问题描述】:

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

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.MySQL方言 com.mysql.jdbc.Driver jdbc:mysql://localhost: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>

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

最好的问候, 瓦尔特·恩里克。

【问题讨论】:

  • “尝试插入另一个”是什么意思?如果在同一个 JVM 中执行,为什么还要再次执行静态初始化程序?
  • @axtavt 当我尝试在我的数据库中插入另一个用户时,我的意思是。
  • @Valter:你是从 NetBeans 开始的,对吧?您是否尝试过创建war 文件并将其部署到单独安装的Tomcat 中?
  • @axtavt 我没有尝试过,因为 netbenas 与 tomcat 集成,这意味着效率更高,我的意思是,我的代码和 netbeans 动态部署。但是您认为 Netbeans 在部署方面做错了吗?我也看到有些人在谈论日食。我认为这是 tomcat 中的一些问题.. 但这对我来说似乎很奇怪,因为这是一个给出这种异常的简短应用程序。
  • @Valter:根据您的描述,HibernateUtil 的静态初始化程序似乎被调用了两次。如果是这样,它可能是由一些与类加载器相关的魔法引起的,例如,用于热重新部署。所以,我认为你需要在没有 IDE 的干净 Tomcat 上尝试一下。

标签: java hibernate exception out-of-memory


【解决方案1】:

在 Hibernate 和大型项目中很常见。 PermGen 是存储类的地方(这不是堆!)。现在每个类都进入 PermGen,如果项目足够大,默认大小 64MB 已经不够用了。

Hibernate 为您的实体动态生成代理类。这可能是您在 Hibernate 上下文中收到此错误的原因。生成的类也可能填充 PermGen。

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

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

【讨论】:

  • 现在我更了解发生了什么,感谢您的评论 Daniel。
  • 我认为代理类是我最后的原因,谢谢。
【解决方案2】:

我之前也遇到过这个问题,发现是之前数据库连接池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);
        }
    }

【讨论】:

    【解决方案3】:

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

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

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

    如果两个问题的答案都是“是”,那么这很可能是您的问题。

    有三种解决方案:

    • 不要热加载。或者至少更频繁地完全重启您的 Web 容器。

    • 使用-XX:MaxPermSize=...增加永久堆的限制

    • 追踪并修复实际导致存储泄漏的任何问题。

    在热加载时会出现一种隐匿的泄漏综合症。保留对使用某些热加载类的旧版本创建的对象实例的引用将泄漏由类类加载器加载的所有类及其所有静态数据。


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

    【讨论】:

    • 嗨,斯蒂芬,这是我的情况,对您的两个问题都是肯定的,我将重新启动更多,并且我已经增加了我的 -xx:MaxPermSize,我将尝试找出导致此存储泄漏的原因。谢谢。
    【解决方案4】:

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

    【讨论】:

    • 我觉得太奇怪了,我的场景是tomcat 6(最新版本)+ netbeans 6.9.1 + hibernate。
    • 你有没有尝试增加 maxpermsize ?..
    • 我现在改变,我按照这个教程:mkyong.com/tomcat/tomcat-javalangoutofmemoryerror-permgen-space,但是即使我改变大小,这个错误也不会再次发生?
    • 如果你是从 netbeans 启动 tomcat,你应该使用 netbeans 进行更改..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 2014-11-06
    相关资源
    最近更新 更多