【问题标题】:How do I use swing in a shutdown hook?如何在关闭挂钩中使用 swing?
【发布时间】:2012-08-25 07:23:43
【问题描述】:

是否有任何可能的方法将 swing 添加到关闭挂钩中(即,在 VM 关闭时显示一个弹出窗口)?

我意识到如果我尝试创建一个新的 JFrame,它会给我一个错误,因为它尝试注册一个关闭挂钩,但由于 VM 已经关闭,该挂钩失败。我只是想知道实际上是否有任何解决方法

【问题讨论】:

  • 我会说不,即使你能,我也建议你不要
  • @MadProgrammer 我环顾四周,找不到任何东西,但我认为这应该是可能的,因为许多应用程序都会给你一个弹出窗口,不仅仅是在关闭时,而且就像你关闭计算机(进而关闭 Java VM)
  • 我有一个程序最近抛出异常,因为开发人员正在关闭挂钩中访问 Swing 组件(我认为是在 Java 7 下)。我想说你在尝试遵循这个概念时可能会遇到问题。部分问题在于不知道 JVM 实际处于什么状态,或者关闭挂钩的调用顺序
  • @AlexColeman 当然可以显示一个弹出窗口,但不能像您假设的那样通过关闭挂钩。通常在关窗事件中完成。
  • 在 Macintosh 上,您可以拥有一个 ApplicationListener,它具有一个 public void handleQuit(ApplicationEvent) 方法。如果你想支持/拥有一台 Windows 机器,这是行不通的,因为它在 com.apple 包中。

标签: java swing shutdown


【解决方案1】:

你真的不应该这样做。来自the Runtime.addShutdownHook specification

Java 虚拟机关闭以响应两种事件:

  • 程序正常退出,当最后一个非守护线程退出或调用exit(相当于System.exit)方法时,或
  • 虚拟机终止以响应用户中断,例如输入^C,或系统范围的事件,例如用户注销或系统关闭。

...

关闭挂钩在虚拟机生命周期的一个微妙时刻运行,因此应该进行防御性编码。特别是,它们应该写成线程安全的,并尽可能避免死锁。他们也不应该盲目依赖可能已经注册了自己的关闭钩子的服务,因此他们自己可能正在关闭过程中。例如,尝试使用其他基于线程的服务(例如 AWT 事件调度线程)可能会导致死锁。

关闭挂钩也应该快速完成它们的工作。当程序调用exit 时,期望虚拟机将立即关闭并退出。当虚拟机由于用户注销或系统关闭而终止时,底层操作系统可能只允许关闭和退出的固定时间量。因此,不建议尝试任何用户交互或在关闭挂钩中执行长时间运行的计算。

...

在极少数情况下,虚拟机可能会中止,也就是说,在没有完全关闭的情况下停止运行。当虚拟机在外部终止时会发生这种情况,例如在 Unix 上使用 SIGKILL 信号或在 Microsoft Windows 上使用 TerminateProcess 调用。如果本地方法出错,例如破坏内部数据结构或尝试访问不存在的内存,虚拟机也可能中止。如果虚拟机中止,则无法保证是否会运行任何关闭挂钩。

此处的具体警告建议您不要这样做:

  1. “关闭挂钩也应该快速完成它们的工作。”

    依赖可能需要一段时间才能完成工作的任何事情,或者像JOptionPane 对话框这样无限期地阻止用户输入,不是你应该做的事情在您的关闭挂钩中。

  2. “尝试使用其他基于线程的服务,例如 AWT 事件调度线程,可能会导致死锁”

    Swing 在 AWT 之上运行,其底层事件调度线程也可能正在关闭。在关闭时尝试使用 Swing 或 AWT 不仅会导致死锁,而且可能根本无法正常工作。

  3. “如果虚拟机中止,则无法保证是否会运行任何关闭挂钩”

    无法保证您的用户甚至可能收到您的消息,因为只有在正常退出或终止时才能保证关闭挂钩运行 - 在停止或中止时运行。

【讨论】:

  • 这是我之前了解的,希望有办法,但我想没有
【解决方案2】:

关闭挂钩应该尽快执行。这不包括等待用户确认对话。在任何情况下,您都无法保证 Swing 事件线程仍在运行。

你不能这样做。

【讨论】:

  • +1 nice "你无法保证 Swing 事件线程仍在运行"
【解决方案3】:

如果有,它不会帮助你。

关闭挂钩是作为 JVM 关闭的一部分异步调用的,因此“确认”对话框不会真正确认任何内容,因为您无法停止或反转关闭过程。等待用户做出决定并不是关闭钩子所要做的那种动作。交互式程序中的关闭挂钩没有意义。 关闭钩子的真正用例是:

用于在 JVM 关闭时释放资源和其他管理

同样重要的是要注意关闭挂钩不会始终运行,更多信息请参见我的回答:How to shutdown java application correctly from C# one

【讨论】:

  • 即使它是异步处理的,线程仍然不是守护进程,因此它可能仍然工作......不是你应该永远这样做。
  • @veer true 但我猜 OP 将面临的最大问题是并非所有应用程序的终止都会调用关闭挂钩
【解决方案4】:
  1. Swing GUI 必须在Event Dispatch Thread 上完成,然后

  2. Simple way,但需要最终用户操作(关闭JDialog

【讨论】:

  • 恐怕我看不出您的回答与原始问题有什么相关性。
  • @DuncanJones 他正在回答。他的回答是关于关闭挂钩 + 可能解决方案的链接......
  • @mKorbel 我看不出第一个选项是如何工作的;我不是要求关闭挂钩,它是随机发生的,我只想用一个弹出窗口来处理它。第二,我看到了一些潜力,但是,当 JVM/计算机关闭时,Runtime#exec 会工作吗?
  • @Alex Coleman Runtime#exec 是七个选项之一,如果您有不明白的地方,请搜索有关 JVM、Swing 以及为什么 Shutdown Hook 不适用于 Swing GUI 的问题有背景任务
【解决方案5】:

我不确定您的问题,但我认为当 JVM 关闭时它不可能运行或显示弹出窗口。就像你准备睡觉时试图跑步一样?只是猜测。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-13
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    相关资源
    最近更新 更多