简体   繁体   English

检测到JVM正在关闭

[英]Detecting that JVM is shutting down

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. 我有一个使用addShutdownHook()处理Ctrl + C的Swing应用程序,并且在我执行的其中一个关闭任务中调用了一个函数,该函数在正常情况下会更改JLabel文本,然后将其挂起,它可以正常工作。

I assume the problem is that the Swing EDT has either terminated or is waiting for something. 我认为问题是Swing EDT已终止或正在等待某些东西。

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? 是否有办法确定EDT已终止或已“完成”(因此我可以避免调用Swing方法),或防止Ctrl-C出现通常的“ windows-all-the-windows-down”行为?


Just to clarify: 只是澄清一下:

I have a method in a class called stop() . 我在一个名为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. 在正常情况下,可以调用此方法(及其补码start() ),并且它会触发一连串的事件,从而导致JLabel进行更新,以获取出现stop()视觉反馈。

When my shutdown hook runs, I need to call stop() to gracefully shutdown some resources. 当我的关闭挂钩运行时,我需要调用stop()以正常关闭一些资源。

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. 我要问的是如何检测到Swing EDT不存在,因此我可以重写stop()以便它检测到缺少Swing并避免调用Swing函数。

The following hack helps to determine whether JVM is in the process of shutting down without passing any flags around: 以下hack帮助确定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;
}

But don't forget about possible concurrency issues. 但是不要忘记可能存在的并发问题。

Shutdown hooks should not expect other services to be in a known state (eg the UI event-handling thread, etc.), because the application has been requested to be shut down. 关闭挂钩不应期望其他服务处于已知状态(例如,UI事件处理线程等),因为已请求关闭应用程序。 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. 编写关闭挂钩以尝试更新挂钩控制范围内的100%以外的内容可能会导致此问题以及其他行为,因此很难进行故障排除。

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. addShutdownHook方法专门提到了这种情况,并警告您不要尝试这些类型的操作,因为这样做很容易导致意外的后果,例如您观察到的锁定。

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. 在这种情况下,由于Swing是您无法控制的多线程UI系统,因此建议您不要在程序生命周期的关闭阶段尝试更改UI中的任何内容。 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?" 我想我的后续问题将是:“为什么要/需要在关闭过程中更改JLabel?” 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) 如果要在关机之前更改某些状态, 最好的方法是将键盘输入作为常规事件捕获(防止它导致应用程序关闭),更改JLabel文本,然后开始关机通过调用System.runFinalization()和/或System.ext(int)自己创建应用程序

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. 我最终在关闭钩子的开头设置了一个标志,并通过stop()方法将此标志(通过提前设置的对象)传递给了该对象,以便它可以测试该标志并决定是否调用Swing方法。

If the shutdown flag is not set, the Swing methods get called. 如果未设置关闭标志,则调用Swing方法。 Otherwise they don't. 否则他们不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM