3

I have a standard Java application which hangs when shutting down. I have been trying to figure out what is causing it to hang, but so far I haven't found anything useful.

This is a thread dump from when I have tried to stop the application:

2014-09-11 11:49:31
Full thread dump Java HotSpot(TM) Client VM (24.51-b03 mixed mode):

"DestroyJavaVM" prio=6 tid=0x19fbbc00 nid=0x22f8 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"pool-3-thread-1" prio=6 tid=0x19fbdc00 nid=0x13c4 waiting on condition [0x2721f000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0affc368> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

"pool-4-thread-1" prio=6 tid=0x19fbd400 nid=0x2010 waiting on condition [0x2729f000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0ad38c80> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

"HSQLDB Timer @1e75cb0" daemon prio=6 tid=0x19fbd000 nid=0x8f4 in Object.wait() [0x2709f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x0ad4f1f0> (a org.hsqldb.lib.HsqlTimer$TaskQueue)
        at org.hsqldb.lib.HsqlTimer$TaskQueue.park(Unknown Source)
        - locked <0x0ad4f1f0> (a org.hsqldb.lib.HsqlTimer$TaskQueue)
        at org.hsqldb.lib.HsqlTimer.nextTask(Unknown Source)
        - locked <0x0ad4f1f0> (a org.hsqldb.lib.HsqlTimer$TaskQueue)
        at org.hsqldb.lib.HsqlTimer$TaskRunner.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

"Grizzly-HttpSession-Expirer" daemon prio=6 tid=0x19fbc800 nid=0x27dc waiting on condition [0x1b27f000]
   java.lang.Thread.State: TIMED_WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0a87eb58> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.parkNanos(Unknown Source)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(Unknown Source)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
        at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

"Service Thread" daemon prio=6 tid=0x00fc2c00 nid=0x21e0 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread0" daemon prio=10 tid=0x00fab000 nid=0x12d0 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" daemon prio=10 tid=0x00fa9c00 nid=0x1ebc waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x00fa6c00 nid=0x23e4 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=0x00f76400 nid=0xe20 in Object.wait() [0x188af000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x09ba5c80> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        - locked <0x09ba5c80> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

"Reference Handler" daemon prio=10 tid=0x00f71000 nid=0x20d8 in Object.wait() [0x186ef000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x09ba5d08> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:503)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
        - locked <0x09ba5d08> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=10 tid=0x00f6fc00 nid=0x229c runnable

"VM Periodic Task Thread" prio=10 tid=0x00fe7800 nid=0x2480 waiting on condition

JNI global references: 204

The interesting thing is that none of the threads listed are from my own code, they all seem to be from the Java standard library, with the exception of the HSQLDB and Grizzly threads. I have tested with a few different JDK distributions, but it doesn't seem to matter.

Does anyone know what I might be doing wrong or how to resolve it?

Thanks

Petter
  • 4,053
  • 27
  • 33
  • 1
    Those pool threads look suspicious. Have you `shutdown`'ed your pool? http://stackoverflow.com/questions/13883293/turning-an-executorservice-to-daemon-in-java – Konstantin V. Salikhov Sep 11 '14 at 10:03
  • I'm not maintaining any thread pools in my code, so it must be coming from somewhere else (I'm using a few third party libs for HTTP server and SSH connections). Do you know if there is any way to find out where it is created? – Petter Sep 11 '14 at 10:35

1 Answers1

2

I found the problem and will post it here in case anyone is interested.

The application used Hibernate along with HSQLDB, and I had created a utility class to simplify handling of EntityManagerFactories. It contained a method like this:

private static javax.persistence.EntityManagerFactory getEntityManagerFactory() {
    if (emf == null) {
        Map properties = new HashMap();
        properties.put("hibernate.connection.url", "jdbc:hsqldb:file:" +
                ConfigurationUtil.CONFIG_DIRECTORY + File.separator +
                "local.db");
        emf = Persistence.createEntityManagerFactory("FPU", properties);
    }
    return emf;
}

What happened was that during startup several threads called this method, causing a number of EntityManagerFactories to be created. This lead to the application not shutting down correctly. Making the above method synchronized solved the problem.

Petter
  • 4,053
  • 27
  • 33