我有一个JavaFX应用程序,有时需要运行单独的进程(updater可执行文件)并终止。
我使用ProcessBuilder.command()
运行一个单独的流程,并观察子流程何时成为!isAlive()
,这意味着流程完全运行。在此之后,我尝试通过运行Window.getWindows().forEach(::dispose)
而不是System.exit(0)
来终止应用程序。
调用System.exit(0)
应用程序挂起后,如果没有单独的进程运行 - 应用程序正确终止。
这是主线程堆栈跟踪的一部分:
" JavaFX应用程序线程" #32 prio = 5 os_prio = 0 Object.wait()中的tid = 0x000000001f4fe000 nid = 0x44d0 [0x0000000023f4d000] java.lang.Thread.State:WAITING(在对象上 监视器)在java.lang.Object.wait(Native Method)at java.lang.Thread.join(Thread.java:1252) - 已锁定< 0x00000006c21ac608> (java.lang.Thread)在java.lang.Thread.join(Thread.java:1326)at at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106) 在 java.lang.ApplicationShutdownHooks $ 1.run(ApplicationShutdownHooks.java:46) 在java.lang.Shutdown.runHooks(Shutdown.java:123)at java.lang.Shutdown.sequence(Shutdown.java:167)at java.lang.Shutdown.exit(Shutdown.java:212) - 已锁定< 0x00000006c2148fb8> (java.lang.Shutdown的java.lang.Class),java.lang.Runtime.exit(Runtime.java:109)at java.lang.System.exit(System.java:971)
所以看来应用程序等待ApplicationShutdownHooks
完成一些。
在应用程序中添加了两个钩子,但在删除它们之后,stacktrace保持不变。
可以隐含地添加哪些钩子?也许单独的流程应该以不同的方式运行才能在子流程关闭之前关闭?
UPD:此应用程序实际上不是完整的JavaFX应用程序,而是具有JavaFX部分的AWT应用程序。
答案 0 :(得分:4)
如果您要在JavaFX中退出应用程序,则应使用:
Platform.exit()
使用此方法将使应用程序调用所有关闭方法,例如stop(),您可以在此处查看更多相关信息:Application JavaFX 8
如果没有共享引起问题的代码部分,请查看这是否有助于您的情况。
答案 1 :(得分:2)
您的应用程序仍在等待所有关闭挂钩完成,我希望仍有一些挂钩。
应用程序退出时会自动运行runHooks
方法。应用程序将在完成后退出(除此之外还会执行其他一些清理)。请参阅以下代码:
static void runHooks() {
Collection<Thread> threads;
synchronized(ApplicationShutdownHooks.class) {
threads = hooks.keySet();
hooks = null;
}
for (Thread hook : threads) {
hook.start();
}
for (Thread hook : threads) {
try {
hook.join();
} catch (InterruptedException x) { }
}
}
每个钩子都是尚未启动的Thread
。关闭将启动所有线程(hook.start()
),然后等待所有线程完成/死亡(hook.join()
)。
你的堆栈跟踪显示有一个无法完成的shutdownhook线程。以下是如何找出哪个。
Thread.join()
方法在this
上同步,'locked'行告诉您哪个Thread对象出问题:
at java.lang.Thread.join(Thread.java:1252)
- locked <0x00000006c21ac608> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1326)
这个数字是对象的唯一编号(我认为虚拟内存地址)。此数字应该在应用程序的完整threaddump中,否则,您可以使用调试器在所有关闭挂钩(java.lang.ApplicationShutdownHooks#hooks
)中查找集合中的对象。
在此之后,您可以查看此主题以查看它正在等待的内容。
请注意,您使用的某些库可能会添加shutdownhooks,而不仅仅是您自己的钩子。
答案 2 :(得分:0)
问题在于应用程序结构。
它实际上是一个手动启动JavaFX组件的Swing / AWT应用程序。因此,当调用Platform.exit()
或Systen.exit(0)
时,AWT窗口保持活动状态并阻止应用程序完全终止。
在这种情况下,需要正确配置活动的AWT窗口,然后调用Platform.exit()
:
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.dispose();
Platform.exit()
然后调用Platform.exit()来关闭应用程序的JavaFX部分。