Hibernate4 + c3p0 + Derby - утечка памяти при остановке Tomcat или перезагрузке веб-приложения

У меня есть очень простой шаблон приложения, который включает в себя встроенную базу данных Apache Derby через Hibernate.

У меня есть следующая конфигурация:

     org.hibernate.dialect.DerbyTenSevenDialect
     org.apache.derby.jdbc.EmbeddedDriver 
    
    
    thread
    10
    org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider
    1
    5
    20
    300
    3000
    50
    true
    update
    false
    false
    org.hibernate.cache.NoCacheProvider
    false
    false

и метод init для SessionFactory:

public static void init(String hibernateConfigurationResource,String connectionUrl) {
    try {
        configuration = new Configuration();
        configuration.configure(hibernateConfigurationResource);
        if (connectionUrl == null || connectionUrl.length() == 0) {
            connectionUrl = "myDb";
        } else {
            connectionUrl += File.separator + "myDb";
        }
        File f = new File(connectionUrl);
        if (logger.isDebugEnabled()) {
            logger.debug("Using db path: " + f.getAbsolutePath());
        }
        if (!f.exists()) {
            if (logger.isDebugEnabled()) {
                logger.debug("Database does not exist: creating");
            }
            connectionUrl += ";create=true";
        }
        configuration
                .setProperty("hibernate.connection.url", "jdbc:derby:"
                    + connectionUrl);

        serviceRegistry =
            new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    } catch (Throwable ex) {
        throw new ExceptionInInitializerError(ex);
    }
}

и на этапе уничтожения этот метод называется:

public static void destroy() throws SQLException {
    String connectionUrl = configuration
            .getProperty("hibernate.connection.url").replace(";create=true", "");
    try {
        if (logger.isDebugEnabled()) {
            logger.debug("Shutting down database: " + connectionUrl);
        }
        DriverManager.getConnection(connectionUrl + ";shutdown=true");
    } catch (SQLNonTransientConnectionException e) {
        if (logger.isDebugEnabled()) {
            logger.debug(e.getMessage());
        }
        String message = e.getMessage();
        if (!(message.startsWith("Database") && message
                .endsWith("shutdown."))) {
            throw e;
        }
    }
    try {
        Session s = sessionFactory.getCurrentSession();
        if (s.isDirty()) {
            s.flush();
        }
        s.disconnect();
        s.close();
        sessionFactory.close();
    } catch (Exception e) {
        logger.error(e);
    }

    Enumeration drivers = DriverManager.getDrivers();
    while (drivers.hasMoreElements()) {
        Driver driver = drivers.nextElement();
        try {
            logger.info("Deregistering jdbc driver: " + driver);
            DriverManager.deregisterDriver(driver);
        } catch (SQLException e) {
            logger.warn("Error deregistering driver " + driver, e);
        }

    }
}

Я заметил, что приложение работает нормально, но как только я остановил кота, я вижу следующие сообщения:

INFO: Stopping service Catalina
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/myWebApp-webapp] appears to have started a thread named [Timer-1] but has failed to stop it. This is very likely to create a memory leak.
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/myWebApp-webapp] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0] but has failed to stop it. This is very likely to create a memory leak.
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/myWebApp-webapp] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1] but has failed to stop it. This is very likely to create a memory leak.
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/myWebApp-webapp] appears to have started a thread named [com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2] but has failed to stop it. This is very likely to create a memory leak.
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/myWebApp-webapp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@106f4e54]) and a value of type [org.apache.derby.iapi.services.context.ContextManager] (value [org.apache.derby.iapi.services.context.ContextManager@587cc9a3]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/myWebApp-webapp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@106f4e54]) and a value of type [org.apache.derby.iapi.services.context.ContextManager] (value [org.apache.derby.iapi.services.context.ContextManager@2e704a6]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
apr 17, 2013 4:34:36 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/myWebApp-webapp] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@106f4e54]) and a value of type [org.apache.derby.iapi.services.context.ContextManager] (value [org.apache.derby.iapi.services.context.ContextManager@36bc4735]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 
apr 17, 2013 4:34:36 PM org.apache.coyote.AbstractProtocolHandler stop
INFO: Stopping ProtocolHandler ["http-bio-8080"]
apr 17, 2013 4:34:36 PM org.apache.coyote.AbstractProtocolHandler stop
INFO: Stopping ProtocolHandler ["ajp-bio-8009"]

Я почти уверен, что проблема на уровне пула соединений, поскольку Hibernate не может правильно отключить провайдер соединений c3p0. Я пробовал также с MySQL, и проблема все еще там.

Мне также известно о защите Tomcat от утечек памяти (которая фактически генерирует эти сообщения), и я использую Tomcat 7.0.39.

Кроме того, я нене хочу перемещать пул соединений за пределы приложения (делегируя контейнер).

Как я могу сказать Hibernate, чтобы все отключилось должным образом и избежать этих сообщений? Что мне не хватает?

Заранее спасибо!

РЕДАКТИРОВАТЬ:

В журнале по выключению просто показывают:

2013-04-18 10:27:13,537 DEBUG [Thread-13] HibernateUtil  - Shutting down database: jdbc:derby:myDb
2013-04-18 10:27:13,555 DEBUG [Thread-13] HibernateUtil  - Database 'myDb' shutdown.
2013-04-18 10:27:13,656 DEBUG [Thread-13] SessionImpl  - Disconnecting session
2013-04-18 10:27:13,656 DEBUG [Thread-13] LogicalConnectionImpl  - Releasing JDBC connection
2013-04-18 10:27:13,658 DEBUG [Thread-13] SessionFactoryImpl  - HHH000031: Closing
2013-04-18 10:27:13,659 INFO  [Thread-13] HibernateUtil  - Deregistering jdbc driver: sun.jdbc.odbc.JdbcOdbcDriver@35849932
2013-04-18 10:27:13,659 INFO  [Thread-13] HibernateUtil  - Deregistering jdbc driver: org.apache.derby.jdbc.AutoloadedDriver40@7d7ff794

При запуске у меня есть только следующая строка для класса AbstractPoolBackedDataSource:

2013-04-18 10:25:38,808 INFO  [Thread-2] AbstractPoolBackedDataSource  - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@28fe617e [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@8c36e25a [ acquireIncrement -> 1, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -> false, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 2s05jr8u7u65au1gs0zth|25e62c36, idleConnectionTestPeriod -> 3000, initialPoolSize -> 3, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 300, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 50, maxStatementsPerConnection -> 0, minPoolSize -> 5, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@423e8f48 [ description -> null, driverClass -> null, factoryClassLocation -> null, identityToken -> 2s05jr8u7u65au1gs0zth|363bec9c, jdbcUrl -> jdbc:derby:myDb, properties -> {user=******, password=******} ], preferredTestQuery -> null, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> true, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false; userOverrides: {} ], dataSourceName -> null, factoryClassLocation -> null, identityToken -> 2s05jr8u7u65au1gs0zth|43ba9cea, numHelperThreads -> 3 ]

Ответы на вопрос(2)

Ваш ответ на вопрос