title: Hibernate4 + c3p0 + Derby - Memory Leak on Tomcat stop or web application reload
body: <p>I have a very simple application template which includes an embedded apache derby database through hibernate.</p>
  
  <p>I have the following configuration:</p>
  
  <pre><code>    &lt;property name="hibernate.dialect"&gt; org.hibernate.dialect.DerbyTenSevenDialect&lt;/property&gt;
      &lt;property name="hibernate.connection.driver_class"&gt; org.apache.derby.jdbc.EmbeddedDriver &lt;/property&gt;
      &lt;property name="hibernate.connection.username"&gt;&lt;/property&gt;
      &lt;property name="hibernate.connection.password"&gt;&lt;/property&gt;
      &lt;property name="current_session_context_class"&gt;thread&lt;/property&gt;
      &lt;property name="connection.pool_size"&gt;10&lt;/property&gt;
      &lt;property name="connection.provider_class"&gt;org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider&lt;/property&gt;
      &lt;property name="hibernate.c3p0.acquire_increment"&gt;1&lt;/property&gt;
      &lt;property name="hibernate.c3p0.min_size"&gt;5&lt;/property&gt;
      &lt;property name="hibernate.c3p0.max_size"&gt;20&lt;/property&gt;
      &lt;property name="hibernate.c3p0.timeout"&gt;300&lt;/property&gt;
      &lt;property name="hibernate.c3p0.idle_test_period"&gt;3000&lt;/property&gt;
      &lt;property name="hibernate.c3p0.max_statements"&gt;50&lt;/property&gt;
      &lt;property name="hibernate.c3p0.testConnectionOnCheckout"&gt;true&lt;/property&gt;
      &lt;property name="hibernate.hbm2ddl.auto"&gt;update&lt;/property&gt;
      &lt;property name="cache.use_second_level_cache"&gt;false&lt;/property&gt;
      &lt;property name="cache.use_query_cache"&gt;false&lt;/property&gt;
      &lt;property name="cache.provider_class"&gt;org.hibernate.cache.NoCacheProvider&lt;/property&gt;
      &lt;property name="hibernate.show_sql"&gt;false&lt;/property&gt;
      &lt;property name="hibernate.format_sql"&gt;false&lt;/property&gt;
  </code></pre>
  
  <p>and a the init method for the SessionFactory is:</p>
  
  <pre><code>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);
      }
  }
  </code></pre>
  
  <p>and at the destroy phase, this method is called:</p>
  
  <pre><code>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") &amp;&amp; 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&lt;Driver&gt; 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);
          }
  
      }
  }
  </code></pre>
  
  <p>I noticed that the application is running fine but as soon as I stop the tomcat, I see the following messages:</p>
  
  <pre><code>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"]
  </code></pre>
  
  <p>I am pretty sure that the problem is at the connection pooling level with Hibernate not being able to shut down the c3p0 connection provider properly. I tried also with mysql and the issue is still there.</p>
  
  <p>I am also aware of the tomcat protection against memory leaks (that is actually producing that messages) and I am running Tomcat 7.0.39.</p>
  
  <p>Moreover I don't want to move the connection pool outside the application (delegating the container).</p>
  
  <p>How can I tell hibernate to shutdown everything properly and avoid those messages? What am I missing?</p>
  
  <p>Thank you in advance!</p>
  
  <p>EDIT:</p>
  
  <p>The log on the shutdown just show:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>On the startup I have only the following line for the class AbstractPoolBackedDataSource:</p>
  
  <pre><code>2013-04-18 10:25:38,808 INFO  [Thread-2] AbstractPoolBackedDataSource  - Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@28fe617e [ connectionPoolDataSource -&gt; com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@8c36e25a [ acquireIncrement -&gt; 1, acquireRetryAttempts -&gt; 30, acquireRetryDelay -&gt; 1000, autoCommitOnClose -&gt; false, automaticTestTable -&gt; null, breakAfterAcquireFailure -&gt; false, checkoutTimeout -&gt; 0, connectionCustomizerClassName -&gt; null, connectionTesterClassName -&gt; com.mchange.v2.c3p0.impl.DefaultConnectionTester, debugUnreturnedConnectionStackTraces -&gt; false, factoryClassLocation -&gt; null, forceIgnoreUnresolvedTransactions -&gt; false, identityToken -&gt; 2s05jr8u7u65au1gs0zth|25e62c36, idleConnectionTestPeriod -&gt; 3000, initialPoolSize -&gt; 3, maxAdministrativeTaskTime -&gt; 0, maxConnectionAge -&gt; 0, maxIdleTime -&gt; 300, maxIdleTimeExcessConnections -&gt; 0, maxPoolSize -&gt; 20, maxStatements -&gt; 50, maxStatementsPerConnection -&gt; 0, minPoolSize -&gt; 5, nestedDataSource -&gt; com.mchange.v2.c3p0.DriverManagerDataSource@423e8f48 [ description -&gt; null, driverClass -&gt; null, factoryClassLocation -&gt; null, identityToken -&gt; 2s05jr8u7u65au1gs0zth|363bec9c, jdbcUrl -&gt; jdbc:derby:myDb, properties -&gt; {user=******, password=******} ], preferredTestQuery -&gt; null, propertyCycle -&gt; 0, testConnectionOnCheckin -&gt; false, testConnectionOnCheckout -&gt; true, unreturnedConnectionTimeout -&gt; 0, usesTraditionalReflectiveProxies -&gt; false; userOverrides: {} ], dataSourceName -&gt; null, factoryClassLocation -&gt; null, identityToken -&gt; 2s05jr8u7u65au1gs0zth|43ba9cea, numHelperThreads -&gt; 3 ]
  </code></pre>