我有一个非常简单的应用程序模板,其中包括通过hibernate的嵌入式apache derby数据库。
我有以下配置:
<property name="hibernate.dialect"> org.hibernate.dialect.DerbyTenSevenDialect</property> <property name="hibernate.connection.driver_class"> org.apache.derby.jdbc.EmbeddedDriver </property> <property name="hibernate.connection.username"></property> <property name="hibernate.connection.password"></property> <property name="current_session_context_class">thread</property> <property name="connection.pool_size">10</property> <property name="connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property> <property name="hibernate.c3p0.acquire_increment">1</property> <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.timeout">300</property> <property name="hibernate.c3p0.idle_test_period">3000</property> <property name="hibernate.c3p0.max_statements">50</property> <property name="hibernate.c3p0.testConnectionOnCheckout">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="cache.use_second_level_cache">false</property> <property name="cache.use_query_cache">false</property> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <property name="hibernate.show_sql">false</property> <property name="hibernate.format_sql">false</property>
SessionFactory的init方法是:
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<Driver> 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); } } }
我注意到该应用程序运行正常,但是一旦我停止了tomcat,我会看到以下消息:
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 ]
经过更多研究后,我发现明确地关闭所有连接可以解决此问题:
C3P0Registry.getNumPooledDataSources(); @SuppressWarnings({ "unchecked", "rawtypes" }) Iterator<Set> it = C3P0Registry.getPooledDataSources().iterator(); while (it.hasNext()) { try { dataSource = (PooledDataSource) it.next(); dataSource.close(); } catch (Exception e) { logger.error(e); } }