从 ShutdownHook 访问 AWT
我试图提供一个非常简单的“您想保存此文档吗?”关闭我的应用程序时的对话框。
我使用了 WindowAdapter 来执行此操作。如果使用任何 GUI 操作关闭应用程序(单击“关闭”按钮、从任务栏关闭、使用“结束任务”从任务管理器关闭),这将非常有效。
然而,当用户注销或杀死应用程序进程时,JVM应用程序会直接收到终止信号。它会关闭所有 AWT 资源,无需用户确认,也无需调用 WindowAdapter
。使用 ShutdownHook
不可能进行任何 GUI 交互,因为 AWT 事件调度线程已经停止。
到目前为止,我已经找到了多种方法来解决此问题:
- 使用 JNI 或 JNA 在终止信号到达 AWT 子系统之前捕获该信号。
- 每个操作系统都需要单独的代码。
- 使用 sun.misc.SignalHandler 捕获终止信号。
- 使用 SUN 专有接口。不保证在其他虚拟机上工作。
- 使用 SWT 在终止信号到达 AWT 子系统之前捕获该信号。
- 维护良好的界面,但我讨厌仅仅为了解决这个小问题而引入 SWT。
- 将用户数据保存到临时文件中,并在程序再次启动时进行清理。
还有其他更好的方法来解决这个问题吗?没有标准的方法来实现如此基本的东西似乎很奇怪。我不能以某种方式再次启动 AWT 子系统吗?
I am trying to provide a very simple "Do you wish to save this document?" dialog upon shutdown of my application.
I have used a WindowAdapter
to do this. This works perfectly if the application is closed using any GUI action (clicking the CLOSE button, closing from the task bar, closing from the Task Manager using End Task).
However, when the user logs off or kills the application process, the JVM application receives a termination signal directly. It closes any AWT resources without user confirmation and without calling the WindowAdapter
. Using a ShutdownHook
, it is not possible to have any GUI interaction, because the AWT Event Dispatch Thread has already been stopped.
So far I have found multiple ways to work around this problem:
- Use JNI or JNA to catch the terminate signal before it reaches the AWT subsystem.
- Needs separate code for every operating system.
- Use sun.misc.SignalHandler to catch the terminate signal.
- Uses a SUN proprietary interface. Not guaranteed to work on other VM's.
- Use SWT to catch the terminate signal before it reaches the AWT subsystem.
- Well-maintained interface, but I hate pulling in SWT just to resolve this small problem.
- Save the user data to a temporary file and treat the clean-up when the program is launched again.
Is there another, better way to fix this? It seems strange there is no standard way to implement something so basic and elementary. Can't I boot up the AWT subsystem again in some way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
主机平台拥有运行您的应用程序的 JVM。在 Mac OS X 上,您可以使用
OSXAdapter
,此处进行了讨论。其他系统可能有类似的机制。一种有用的防御措施是使用java.util.prefs.Preferences
记录清理信息。它的平台独立性和典型实现为给定平台提供了最大努力的保留。The host platform owns the JVM running your application. On Mac OS X you can use
OSXAdapter
, discussed here. Other systems may have a similar mechanism. One useful defensive measure is to usejava.util.prefs.Preferences
to record clean-up information. It's platform-independent and typical implementations offer best-effort retention for a given platform.也许您的想法很复杂,而不是终止当前 JVM 实例
1) 隐藏容器
2) 保存应用程序属性,
3) 在异常上显示 JOptionPane 并显示一些有意义的内容
4) 调用 System.exit(0);
5) 一些最大的应用程序(使用 Embedded_database 用于存储本地数据)节省这些进程几秒钟容器隐藏后
0) 也许 帮助您通过此线程了解普通 Java 中的解决方法
Maybe you complicated very simple thinks, instead of terminating current JVM instance
1) hide Container(s)
2) save applications properties,
3) on Exceptions show JOptionPane with something meaningful about
4) call System.exit(0);
5) a few biggest application (with Embedded_database for storing local data) saving these processess a few seconds after Containers hidden
0) maybe help you this thread about workaround in plain vanilla Java