JavaFX 应用程序在 System.exit() 后不会终止
JavaFX application does not terminate after System.exit()
我有一个 JavaFX 应用程序,有时需要 运行 分离进程(更新程序可执行文件)并终止。
我正在 运行 通过使用 ProcessBuilder.command()
设置一个单独的进程,并观察子进程何时会变成 !isAlive()
,这意味着进程 运行 完全。在此之后,我试图通过 运行ning Window.getWindows().forEach(::dispose)
然后 System.exit(0)
.
终止应用程序
调用 System.exit(0)
后应用程序挂起,但如果没有单独的进程 运行 应用程序正确终止。
这是主线程堆栈跟踪的一部分:
"JavaFX Application Thread" #32 prio=5 os_prio=0
tid=0x000000001f4fe000 nid=0x44d0 in Object.wait()
[0x0000000023f4d000] java.lang.Thread.State: WAITING (on object
monitor) at java.lang.Object.wait(Native Method) at
java.lang.Thread.join(Thread.java:1252)
- locked <0x00000006c21ac608> (a java.lang.Thread) at java.lang.Thread.join(Thread.java:1326) at
java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106)
at
java.lang.ApplicationShutdownHooks.run(ApplicationShutdownHooks.java:46)
at java.lang.Shutdown.runHooks(Shutdown.java:123) at
java.lang.Shutdown.sequence(Shutdown.java:167) at
java.lang.Shutdown.exit(Shutdown.java:212)
- locked <0x00000006c2148fb8> (a java.lang.Class for java.lang.Shutdown) at java.lang.Runtime.exit(Runtime.java:109) at
java.lang.System.exit(System.java:971)
所以应用程序似乎在等待 ApplicationShutdownHooks
完成。
应用程序中添加了两个钩子,但删除它们后,stacktrace 保持不变。
可以隐式添加哪些挂钩?也许单独的进程应该运行以不同的方式能够在子进程关闭之前关闭?
UPD:这个应用程序实际上不是一个完整的JavaFX应用程序,而是一个带有JavaFX部分的AWT应用程序。
您的应用程序仍在等待所有关闭挂钩完成,我希望仍然有一些挂钩。
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) { }
}
}
每个hook都是一个Thread
还没有启动的。关闭会启动所有线程 (hook.start()
),然后等待它们全部到 complete/die (hook.join()
)。
您的堆栈跟踪显示有一个未完成的 shutdownhook 线程。这是找出哪个的方法。
Thread.join()
方法在 this
上同步,'locked' 行告诉您哪个线程对象有问题:
at java.lang.Thread.join(Thread.java:1252)
- locked <0x00000006c21ac608> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1326)
这个数字是对象的唯一数字(我认为是虚拟内存地址)。这个数字应该在应用程序的完整线程转储中,或者如果没有,您可以使用调试器在具有所有关闭挂钩 (java.lang.ApplicationShutdownHooks#hooks
) 的集合中查找该对象。
在此之后您可以查看此线程以了解它在等待什么。
请注意,您使用的某些库可能会添加 shutdownhook,而不仅仅是您自己的挂钩。
问题出在应用程序结构中。
它实际上是一个带有手动启动的 JavaFX 组件的 Swing/AWT 应用程序。因此,当 Platform.exit()
或 Systen.exit(0)
被调用时,AWT windows 保持活动状态并阻止应用程序完全终止。
在这种情况下,需要正确处理活动 AWT window 然后调用 Platform.exit()
:
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.dispose();
Platform.exit()
然后调用 Platform.exit() 关闭应用程序的 JavaFX 部分。
我有一个 JavaFX 应用程序,有时需要 运行 分离进程(更新程序可执行文件)并终止。
我正在 运行 通过使用 ProcessBuilder.command()
设置一个单独的进程,并观察子进程何时会变成 !isAlive()
,这意味着进程 运行 完全。在此之后,我试图通过 运行ning Window.getWindows().forEach(::dispose)
然后 System.exit(0)
.
调用 System.exit(0)
后应用程序挂起,但如果没有单独的进程 运行 应用程序正确终止。
这是主线程堆栈跟踪的一部分:
"JavaFX Application Thread" #32 prio=5 os_prio=0 tid=0x000000001f4fe000 nid=0x44d0 in Object.wait() [0x0000000023f4d000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1252)
- locked <0x00000006c21ac608> (a java.lang.Thread) at java.lang.Thread.join(Thread.java:1326) at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106) at java.lang.ApplicationShutdownHooks.run(ApplicationShutdownHooks.java:46) at java.lang.Shutdown.runHooks(Shutdown.java:123) at java.lang.Shutdown.sequence(Shutdown.java:167) at java.lang.Shutdown.exit(Shutdown.java:212)
- locked <0x00000006c2148fb8> (a java.lang.Class for java.lang.Shutdown) at java.lang.Runtime.exit(Runtime.java:109) at java.lang.System.exit(System.java:971)
所以应用程序似乎在等待 ApplicationShutdownHooks
完成。
应用程序中添加了两个钩子,但删除它们后,stacktrace 保持不变。
可以隐式添加哪些挂钩?也许单独的进程应该运行以不同的方式能够在子进程关闭之前关闭?
UPD:这个应用程序实际上不是一个完整的JavaFX应用程序,而是一个带有JavaFX部分的AWT应用程序。
您的应用程序仍在等待所有关闭挂钩完成,我希望仍然有一些挂钩。
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) { }
}
}
每个hook都是一个Thread
还没有启动的。关闭会启动所有线程 (hook.start()
),然后等待它们全部到 complete/die (hook.join()
)。
您的堆栈跟踪显示有一个未完成的 shutdownhook 线程。这是找出哪个的方法。
Thread.join()
方法在 this
上同步,'locked' 行告诉您哪个线程对象有问题:
at java.lang.Thread.join(Thread.java:1252)
- locked <0x00000006c21ac608> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1326)
这个数字是对象的唯一数字(我认为是虚拟内存地址)。这个数字应该在应用程序的完整线程转储中,或者如果没有,您可以使用调试器在具有所有关闭挂钩 (java.lang.ApplicationShutdownHooks#hooks
) 的集合中查找该对象。
在此之后您可以查看此线程以了解它在等待什么。
请注意,您使用的某些库可能会添加 shutdownhook,而不仅仅是您自己的挂钩。
问题出在应用程序结构中。
它实际上是一个带有手动启动的 JavaFX 组件的 Swing/AWT 应用程序。因此,当 Platform.exit()
或 Systen.exit(0)
被调用时,AWT windows 保持活动状态并阻止应用程序完全终止。
在这种情况下,需要正确处理活动 AWT window 然后调用 Platform.exit()
:
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.dispose();
Platform.exit()
然后调用 Platform.exit() 关闭应用程序的 JavaFX 部分。