java 休眠:OutOfMemoryError:永久代空间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5418318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:01:37  来源:igfitidea点击:

Hibernate :OutOfMemoryError: PermGen space

javahibernateexceptionout-of-memory

提问by Valter Silva

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:

更新:我不知道 hibernate.cfg 中是否有什么东西,但在这里:

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

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

org.hibernate.dialect.MySQLDialect 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>

Why this happen and how to fix it ?

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

Best regards, Valter Henrique.

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

回答by Daniel

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

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.

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

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

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

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.

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

回答by Nicholas Hemley

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.

我之前也遇到过这个问题,发现是数据库连接池C3PO之前的内存泄漏导致的,没有正确关闭。

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

因此,解决方案是在取消部署 servlet 上下文时手动硬重置并关闭 C3PO 数据源。

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

因此,在自定义 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);
        }
    }

回答by Stephen C

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.

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

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

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

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

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

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.

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

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

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

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

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

回答by Gursel Koca

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

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