检测到 JVM 正在关闭

发布于 2024-11-26 04:01:04 字数 548 浏览 2 评论 0 原文

我有一个使用 addShutdownHook() 处理 Ctrl+C 的 Swing 应用程序,它工作正常,直到我的关闭任务之一调用一个在正常情况下更改 JLabel 文本的函数,此时它挂起。

我认为问题是 Swing EDT 已终止或正在等待某些内容。

有没有办法确定 EDT 已终止或“完成”(这样我就可以避免调用 Swing 方法),或者阻止 Ctrl-C 上通常的关闭所有窗口行为?


只是为了澄清:

我在一个名为 stop() 的类中有一个方法。在正常情况下,这可以被调用(连同它的补充 start()),并且它会触发一系列导致 JLabel 更新的事件,以获得 stop()< 的视觉反馈/code> 已发生。

当我的关闭挂钩运行时,我需要调用 stop() 来正常关闭一些资源。

我要问的是如何检测 Swing EDT 不存在,因此我可以重写 stop() 以便它检测到 Swing 的缺失并避免调用 Swing 函数。

I have a Swing application that handles Ctrl+C using addShutdownHook(), and it works fine until one of the shutdown tasks I have calls a function that under normal circumstances changes a JLabel text, at which point it hangs.

I assume the problem is that the Swing EDT has either terminated or is waiting for something.

Is there a way to either determine that the EDT has terminated or is "done" (so I can avoid calling Swing methods), or to prevent the usual close-all-the-windows-down behavior on Ctrl-C?


Just to clarify:

I have a method in a class called stop(). Under normal circumstances this can get called (along with its complement start()) and it triggers a cascade of things that causes a JLabel to be updated, for visual feedback that a stop() has occurred.

When my shutdown hook runs, I need to call stop() to gracefully shutdown some resources.

What I'm asking is how I can detect that Swing EDT is not there, so I can rewrite stop() so that it detects a lack of Swing and avoids the call to the Swing functions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

愁以何悠 2024-12-03 04:01:04

以下技巧有助于确定 JVM 是否正在关闭过程中而不传递任何标志:

private static final Thread DUMMY_HOOK = new Thread();

public static boolean isShuttingDown()
{
    try {
        Runtime.getRuntime().addShutdownHook(DUMMY_HOOK);
        Runtime.getRuntime().removeShutdownHook(DUMMY_HOOK);
    } catch ( IllegalStateException e ) {
        return true;
    }

    return false;
}

但不要忘记可能的并发问题。

The following hack helps to determine whether JVM is in the process of shutting down without passing any flags around:

private static final Thread DUMMY_HOOK = new Thread();

public static boolean isShuttingDown()
{
    try {
        Runtime.getRuntime().addShutdownHook(DUMMY_HOOK);
        Runtime.getRuntime().removeShutdownHook(DUMMY_HOOK);
    } catch ( IllegalStateException e ) {
        return true;
    }

    return false;
}

But don't forget about possible concurrency issues.

浅笑依然 2024-12-03 04:01:04

关闭挂钩不应期望其他服务处于已知状态(例如,UI 事件处理线程等),因为应用程序已被请求关闭。编写一个尝试更新并非 100% 在该钩子控制范围内的内容的关闭钩子可能会导致这种行为以及其他难以排除故障的行为。

addShutdownHook 方法特别提到了这种情况,并警告您不应尝试这些类型的操作,因为这样做很容易导致意外后果,例如您观察到的锁定。

来自 文档

关闭挂钩在虚拟机生命周期的微妙时刻运行
机器,因此应该进行防御性编码。他们应该,在
特别是,应编写为线程安全的并避免死锁
尽可能。他们也不应该盲目依赖服务
可能已经注册了自己的关闭挂钩,因此可能
自己正在关闭过程中。

在这种情况下,由于 Swing 是一个您无法控制的多线程 UI 系统,因此我建议您不要在程序生命周期的关闭阶段尝试更改 UI 中的任何内容。这样做会导致奇怪的、不可预测的、有时不可重复的情况,这些情况在一次运行到下一次运行或从一台机器到另一台机器上可能会有所不同,具体取决于线程如何安排关闭。另一个线程如何以及何时停止其工作并不是设计为以线性、可预测的方式发生的。因此,您在多线程程序中编写的任何代码,如果依赖于另一个线程在特定时间处于特定状态(除非这些线程明确地相互通信其状态),那么您将面临这些类型的问题。问题。

我想我的后续问题是,“为什么您想要/需要在关闭过程中更改 JLabel?”如果您想在关闭之前更改某些内容的状态,更好的方法是将键盘输入捕获为常规事件(防止它导致应用程序关闭),更改 JLabel 文本,然后通过调用 System.runFinalization() 和/或 System.ext(int)

Shutdown hooks should not expect other services to be in a known state (e.g. the UI event-handling thread, etc.), because the application has been requested to be shut down. Writing a shutdown hook that tries to update something that isn't 100% within the hook's control can result in this, and other behavior, that will be difficult to troubleshoot.

The addShutdownHook method specifically mentions this case, and warns that you shouldn't try these types of actions, since doing so can easily result in unexpected consequences, such as the lockup you've observed.

From the documentation:

Shutdown hooks run at a delicate time in the life cycle of a virtual
machine and should therefore be coded defensively. They should, in
particular, be written to be thread-safe and to avoid deadlocks
insofar as possible. They should also not rely blindly upon services
that may have registered their own shutdown hooks and therefore may
themselves in the process of shutting down.

In this case, since Swing is a multi-threaded UI system which you do not control, I would recommend not trying to alter anything in the UI at the shutdown stage of you're program's life. Doing so will result in strange, unpredictable, and sometimes non-repeatable situations that can vary from one run to the next, or from one machine to the next, depending on how the threads get scheduled to shutdown. How, and when, another thread stops its work is not designed to happen in a linear, predictable way. As such, any code you write in a multi-threaded program that relies upon another thread being in a certain state at a certain time (unless those threads are clearly communicating with each other about their state), will open you up to these kinds of issues.

I suppose my follow up question would be, "Why do you want/need to alter the JLabel during the shutdown process?" If you want to change the state of something before shutdown, the better way to do it would be catch the keyboard input as a regular event (preventing it from causing the application to close), change the JLabel text, and then start a shutdown of the application yourself via a call to System.runFinalization() and/or System.ext(int)

她如夕阳 2024-12-03 04:01:04

我最终在关闭挂钩的开头设置了一个标志,并使用我的 stop() 方法将此标志(通过提前设置的对象)传达给对象,以便它可以测试该标志并决定是否调用 Swing 方法。

如果未设置关闭标志,则调用 Swing 方法。否则他们不会。

I ended up setting a flag at the beginning of the shutdown hook, and communicating this (via objects set up ahead of time) to the object with my stop() method, so that it can test this flag and decide whether or not to call the Swing methods.

If the shutdown flag is not set, the Swing methods get called. Otherwise they don't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文