System.exit()之后JavaFX应用程序不会终止

时间:2017-11-02 09:41:16

标签: java javafx exit terminate

我有一个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应用程序。

3 个答案:

答案 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部分。