0

I'm running tomcat under/inside of eclipse while developing a web application. The web app is using hsqldb in embedded mode, via hibernate and guice. Things seem to be working fine, except when I stop tomcat. Eclipse has a green start button and a red stop button for Tomcat. When I click on the stop button it doesn't immediately stop it nicely like it did before I added hibernate and hsqldb to the mix. Now it waits a few seconds and then eclipse gives me a dialog box about not being able to stop tomcat and to click OK to force it to terminate.

Does anyone know what I need to do to fix this? I found some other responses saying to put the hsqldb jar file in tomcat's lib directory but I was wondering there is anything I could do that's a little less drastic.

Here's what's in the error output from tomcat (in the eclipse console window):

Jan 31, 2017 7:04:11 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesJdbc
WARNING: The web application [basic] registered the JDBC driver [org.hsqldb.jdbc.JDBCDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jan 31, 2017 7:04:11 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [basic] appears to have started a thread named [HSQLDB Timer @276f0355] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)
 org.hsqldb.lib.HsqlTimer$TaskQueue.park(Unknown Source)
 org.hsqldb.lib.HsqlTimer.nextTask(Unknown Source)
 org.hsqldb.lib.HsqlTimer$TaskRunner.run(Unknown Source)
 java.lang.Thread.run(Thread.java:745)
Jan 31, 2017 7:04:11 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [basic] appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
Jan 31, 2017 7:04:11 PM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
SEVERE: The web application [basic] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@1d4fc7e8]) and a value of type [org.hibernate.internal.SessionImpl] (value [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]) 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.
lumpynose
  • 967
  • 4
  • 12
  • You need to SHUTDOWN the database when you stop Tomcat. – fredt Feb 01 '17 at 14:17
  • lumpynose is rigth, you have two solutions : - run "SHUTDOWN;" as an SQL command somewhere at the end of your app OR use shutdown = true in your connexion string like this : _Connection = DriverManager.getConnection("jdbc:hsqldb:file:mydb;shutdown=true", "SA", ""); – Julien R Feb 02 '17 at 02:43

1 Answers1

0

I have a stupid answer but I'll show you what I did.

@JulienR: I already had the shutdown=true in my persistence.xml file for the javax.persistence.jdbc.url value.

I created a ServletContextListener and added it to my web.xml file; here's the code. The first part that uses the EntityManager to issue the SHUTDOWN command is my code. The code for the ClassLoader and driver eyeballing I got off of here. So with this it's no longer complaining about HSQLDB but I'm still getting a WARNING about two threads that weren't stopped (and I have to wait for eclipse to time out waiting for it). I've appended the relevant lines from the log.

public class BasicServletContextListener implements ServletContextListener {
    private final transient Logger log =
        LoggerFactory.getLogger(BasicServletContextListener.class);

    // private final Provider<EntityManager> entityManagerProvider;

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        this.log.debug("contextEvent: {}", event.toString());

        final EntityManagerFactory entityManagerFactory =
            Persistence.createEntityManagerFactory("ilmp");

        final EntityManager entityManager =
            entityManagerFactory.createEntityManager();

        entityManager.getTransaction().begin();

        final Query query =
            entityManager.createNativeQuery("SHUTDOWN COMPACT;");

        this.log.debug("query: {}", query.executeUpdate());

        entityManager.getTransaction().commit();

        entityManager.close();

        // Now deregister JDBC drivers in this context's ClassLoader:
        // Get the webapp's ClassLoader
        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
        // Loop through all drivers
        final Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            final Driver driver = drivers.nextElement();
            if (driver.getClass().getClassLoader() == cl) {
                // This driver was registered by the webapp's
                // ClassLoader, so deregister it:
                try {
                    this.log.info("Deregistering JDBC driver {}", driver);
                    DriverManager.deregisterDriver(driver);
                }
                catch (final SQLException ex) {
                    this.log.error("Error deregistering JDBC driver {}", driver,
                                   ex);
                }
            }
            else {
                // driver was not registered by the webapp's
                // ClassLoader and may be in use elsewhere
                this.log.trace(
                               "Not deregistering JDBC driver {} as it does not belong to this webapp's ClassLoader",
                               driver);
            }
        }
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        this.log.debug("contextEvent: {}", event.toString());
    }
}

>

 INFO: 2017-Feb-01 19:05:36.023 [localhost-startStop-2] org.hibernate.hql.internal.QueryTranslatorFactoryInitiator.initiateService.47: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: SHUTDOWN COMPACT;
 INFO: 2017-Feb-01 19:05:36.226 [localhost-startStop-2] sun.reflect.NativeMethodAccessorImpl.invoke0.-2: Database closed
 INFO: 2017-Feb-01 19:05:36.273 [localhost-startStop-2] sun.reflect.NativeMethodAccessorImpl.invoke0.-2: open start - state not modified
 INFO: 2017-Feb-01 19:05:36.351 [localhost-startStop-2] sun.reflect.NativeMethodAccessorImpl.invoke0.-2: Database closed
DEBUG: 2017-Feb-01 19:05:36.460 [localhost-startStop-2] com.objecteffects.basic.persist.BasicServletContextListener.contextDestroyed.42: query: 0
 INFO: 2017-Feb-01 19:05:36.460 [localhost-startStop-2] com.objecteffects.basic.persist.BasicServletContextListener.contextDestroyed.59: Deregistering JDBC driver org.hsqldb.jdbc.JDBCDriver@3cd32e8d
Feb 01, 2017 7:05:36 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [basic] appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
Feb 01, 2017 7:05:36 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [basic] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 java.lang.Thread.run(Thread.java:745)
Feb 01, 2017 7:05:36 PM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
SEVERE: The web application [basic] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@1bc6eba0]) and a value of type [org.hibernate.internal.SessionImpl] (value [SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.objecteffects.basic.persist.TumblrSecretsEntity#1], EntityKey[com.objecteffects.basic.persist.TumblrSecretsEntity#2]],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]) 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.
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-nio-8080"]
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["ajp-nio-8009"]
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-nio-8080"]
Feb 01, 2017 7:05:36 PM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["ajp-nio-8009"]

The stupid answer is that I looked at my setup for something I wrote several years ago (I'm retired and just dinking around trying to write something for myself) and adding the c3p0 config lines I'd used previously to this persistence.xml makes it shut down without the delay, although I still get a bunch of warnings about zombie threads. Here are the relevant lines (still commented out).

<!--             <property -->
<!--                 name="hibernate.c3p0.min_size" -->
<!--                 value="5" /> -->

<!--             <property -->
<!--                 name="hibernate.c3p0.max_size" -->
<!--                 value="20" /> -->

<!--             <property -->
<!--                 name="hibernate.c3p0.timeout" -->
<!--                 value="1800" /> -->

<!--             <property -->
<!--                 name="hibernate.c3p0.max_statements" -->
<!--                 value="50" /> -->
Community
  • 1
  • 1
lumpynose
  • 967
  • 4
  • 12