7

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

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

4

5 回答 5

14

你真的不应该这样做。从规范_Runtime.addShutdownHook

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

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

...

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

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

...

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

此处的特定警告建议您要这样做:

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

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

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

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

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

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

于 2012-08-25T08:18:47.423 回答
4

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

你不能这样做。

于 2012-08-25T08:18:08.160 回答
2
  1. Swing GUI 必须在Event Dispatch Thread上完成,然后

  2. 简单的方法,但需要最终用户操作(关闭JDialog

于 2012-08-25T07:30:13.637 回答
2

如果有,它不会帮助你。

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

用于在 JVM 关闭时释放资源和其他内务处理

同样重要的是要注意关闭钩子不会总是运行,更多信息请参见我的答案:如何从 C# 中正确关闭 Java 应用程序

于 2012-08-25T08:06:48.837 回答
-1

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

于 2012-08-25T08:09:58.883 回答