如何确定我的Java应用程序拒绝干净地终止的原因?

时间:2015-07-20 19:14:22

标签: java debugging intellij-idea

我发现在某些情况下,当我关闭JavaFX桌面应用程序窗口时,JVM不会终止。我被迫从IntelliJ IDEA中杀死了这个过程。

我是否可以使用任何工具或程序来确定阻碍应用程序的内容?我试着从调试视图中查看运行线程,但没有看到任何明显的东西。

我看到以下线程正在运行:

"pool-4-thread-1@5149" prio=5 tid=0x19 nid=NA waiting
  java.lang.Thread.State: WAITING
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
      at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
      at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

"pool-3-thread-1@5126" prio=5 tid=0x18 nid=NA waiting
  java.lang.Thread.State: WAITING
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
      at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
      at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

"Prism Font Disposer@3380" daemon prio=10 tid=0x16 nid=NA waiting
  java.lang.Thread.State: WAITING
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
      at com.sun.javafx.font.Disposer.run(Disposer.java:93)
      at java.lang.Thread.run(Thread.java:745)

"Thread-1@800" daemon prio=5 tid=0x10 nid=NA waiting
  java.lang.Thread.State: WAITING
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
      at java.util.concurrent.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:492)
      at com.sun.glass.ui.InvokeLaterDispatcher.run(InvokeLaterDispatcher.java:108)

"AWT-Windows@5905" daemon prio=6 tid=0x1c nid=NA runnable
  java.lang.Thread.State: RUNNABLE
      at sun.awt.windows.WToolkit.eventLoop(WToolkit.java:-1)
      at sun.awt.windows.WToolkit.run(WToolkit.java:306)
      at java.lang.Thread.run(Thread.java:745)

"Java2D Disposer@5290" daemon prio=10 tid=0x1a nid=NA waiting
  java.lang.Thread.State: WAITING
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
      at sun.java2d.Disposer.run(Disposer.java:148)
      at java.lang.Thread.run(Thread.java:745)

"Finalizer@428" daemon prio=8 tid=0x3 nid=NA waiting
  java.lang.Thread.State: WAITING
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
      at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler@429" daemon prio=10 tid=0x2 nid=NA waiting
  java.lang.Thread.State: WAITING
      at java.lang.Object.wait(Object.java:-1)
      at java.lang.Object.wait(Object.java:502)
      at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)

"DestroyJavaVM@6048" prio=5 tid=0x1f nid=NA runnable
  java.lang.Thread.State: RUNNABLE

"Thread-2@900" daemon prio=5 tid=0x12 nid=NA runnable
  java.lang.Thread.State: RUNNABLE

"Attach Listener@426" daemon prio=5 tid=0x5 nid=NA runnable
  java.lang.Thread.State: RUNNABLE

"Signal Dispatcher@427" daemon prio=9 tid=0x4 nid=NA runnable
  java.lang.Thread.State: RUNNABLE

2 个答案:

答案 0 :(得分:3)

当剩下的唯一用户线程是守护程序线程时,JVM将终止。查看您的线程转储,我们可以看到两个不是仍在运行的守护程序线程的线程:

"pool-4-thread-1@5149" prio=5 tid=0x19 nid=NA waiting
  java.lang.Thread.State: WAITING
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
      ...

"pool-3-thread-1@5126" prio=5 tid=0x18 nid=NA waiting
  java.lang.Thread.State: WAITING
      at sun.misc.Unsafe.park(Unsafe.java:-1)
      at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
      ...

这些线程会阻止JVM终止。

根据名称判断它们可能是从代码中的线程池中生成的。由于他们正在等待,他们只是你池中的空闲线程。有几个选项可以确保这些线程不会阻止JVM终止:

  1. 在您的线程池(或shutdown()或您使用的任何接口)上调用Executor
  2. 使用您自己的线程工厂创建线程池,该线程工厂将线程设置为守护程序线程。
  3. 配置线程池以允许线程超时并自动销毁。

答案 1 :(得分:1)

你有两个非守护程序线程持有你的JVM(pool-4-thread-1 @ 5149& pool-3-thread-1 @ 5126)。

检查应用程序启动的线程是否标记为守护程序线程(使用Thread.setDaemon(true)方法)。当主应用程序线程结束时,任何非守护程序线程仍处于活动状态将阻止应用程序终止。

执行程序的默认threadfactory确保线程不是守护程序线程。从线程的名称来看,它们看起来就像是由执行者创建的。

所以基本上检查你是否有一个忘记关闭的执行程序,或者你使用的库创建了一个并且在离开main之前忘记进行清理的库,这会阻止它关闭执行程序。