Обнаружение, что JVM закрывается - PullRequest
2 голосов
/ 25 июля 2011

У меня есть приложение Swing, которое обрабатывает Ctrl + C с помощью addShutdownHook (), и оно работает нормально, пока одна из задач выключения у меня не вызывает функцию, которая при нормальных обстоятельствах изменяет текст JLabel, после чего он зависает.*

Я предполагаю, что проблема в том, что Swing EDT либо завершился, либо ожидает чего-то.

Есть ли способ определить, что EDT завершен или "завершен" (поэтому я могу избежатьвызывая методы Swing), или чтобы предотвратить обычное поведение закрытия всех окон на Ctrl-C?


Просто чтобы уточнить:

У меня есть метод вкласс под названием stop().При нормальных обстоятельствах это может быть вызвано (вместе с его дополнением start()), и это вызывает каскад вещей, который вызывает обновление JLabel, для визуальной обратной связи, что stop() произошло.

Когда мойзавершает работу shutdown hook, мне нужно вызвать stop(), чтобы корректно завершить работу некоторых ресурсов.

Я спрашиваю, как я могу обнаружить, что Swing EDT не существует, поэтому я могу переписать stop(), чтобы он обнаружил отсутствие Swing и избежал вызова функций Swing.

Ответы [ 3 ]

4 голосов
/ 10 ноября 2011

Следующий хак помогает определить, находится ли 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;
}

Но не забывайте о возможных проблемах параллелизма.

2 голосов
/ 25 июля 2011

Хуки завершения работы не должны ожидать, что другие службы будут в известном состоянии (например, поток обработки событий пользовательского интерфейса и т. Д.), Потому что приложение было запрошено для закрытия.Написание перехвата отключения, который пытается обновить что-то, что не находится на 100% под контролем перехватчика, может привести к этому и другому поведению, которое будет трудно устранить.

Метод addShutdownHook специально упоминает этот случайи предупреждает, что вы не должны пытаться выполнять подобные действия, поскольку это может легко привести к непредвиденным последствиям, таким как блокировка, которую вы наблюдали.

С документация :

Завершающие хуки запускаются в непростое время в жизненном цикле виртуальной машины и поэтому должны кодироваться с защитой.В частности, они должны быть написаны так, чтобы они были поточно-ориентированными и, по возможности, избегали взаимоблокировок.Они также не должны слепо полагаться на сервисы, которые могли зарегистрировать свои собственные ловушки отключения и, следовательно, могут сами в процессе выключения.

В этом случае, поскольку Swing является многопоточной системой пользовательского интерфейса, котораяВы не контролируете, я бы порекомендовал не пытаться изменить что-либо в пользовательском интерфейсе на этапе завершения вашей программы.Это может привести к странным, непредсказуемым, а иногда и неповторимым ситуациям, которые могут варьироваться от одного запуска к следующему или от одного компьютера к другому, в зависимости от того, как запланировано отключение потоков.То, как и когда другой поток прекращает свою работу, не должно происходить линейным, предсказуемым образом.Таким образом, любой код, который вы пишете в многопоточной программе, которая полагается на то, что другой поток находится в определенном состоянии в определенное время (если только эти потоки не сообщаются друг с другом об их состоянии), откроет вам возможность такого родапроблемы.

Я полагаю, что мой следующий вопрос будет: "Почему вы хотите / должны изменить JLabel во время процесса выключения?"Если вы хотите изменить состояние чего-либо перед выключением, то лучший способ сделать это - перехватить ввод с клавиатуры как обычное событие (предотвращающее закрытие приложения), измените текст JLabel,а затем запустите завершение работы приложения самостоятельно с помощью вызова System.runFinalization () и / или System.ext (int)

0 голосов
/ 25 июля 2011

Я закончил тем, что установил флаг в начале ловушки завершения работы и сообщил об этом (с помощью заранее установленных объектов) объекту с помощью моего метода stop(), чтобы он мог проверить этот флаг и решить,не вызывать методы Swing.

Если флаг выключения не установлен, вызывается метод Swing.В противном случае они не делают.

...