Метод выполнения при завершении работы выдает исключение недопустимого состояния log4j, неспособное зарегистрировать завершение работы.

Я хотел бы закрыть соединения при выходе из приложения Swing. Итак, как предлагается здесь: Запуск метода при закрытии программы?

Я добавил следующий код в основной поток, в результате чего получилась следующая трассировка стека. Он выполняет мой метод closeConnections.

/** on exit */
         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {

                public void run() {
                     DeviceManager.getInstance().closeConnections();
                    //shutdown log4j2
                    if( LogManager.getContext() instanceof LoggerContext ) {
                        LogManager.getLogger().info("Shutting down log4j2");
                        Configurator.shutdown((LoggerContext)LogManager.getContext());
                    } else{
                        LogManager.getLogger().warn("Unable to shutdown log4j2");}

                }

            }, "Shutdown-thread"));

ERROR StatusLogger catching java.lang.IllegalStateException: Shutdown in progress
    at java.lang.ApplicationShutdownHooks.add(Unknown Source)
    at java.lang.Runtime.addShutdownHook(Unknown Source)
    at org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry.addShutdownHook(DefaultShutdownCallbackRegistry.java:136)
    at org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry.start(DefaultShutdownCallbackRegistry.java:125)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.initializeShutdownCallbackRegistry(Log4jContextFactory.java:123)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.<init>(Log4jContextFactory.java:89)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.<init>(Log4jContextFactory.java:54)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at org.apache.logging.log4j.LogManager.<clinit>(LogManager.java:96)
    at com.guitarjwindows.repositories.midi.WindowsMidiCommunicator.init(WindowsMidiCommunicator.java:46)
    at com.guitarjwindows.repositories.midi.WindowsMidiCommunicator.<init>(WindowsMidiCommunicator.java:33)
    at com.guitarjwindows.repositories.midi.WindowsMidiCommunicator.getInstance(WindowsMidiCommunicator.java:37)
    at com.guitarjwindows.service.DeviceManager.closeConnections(DeviceManager.java:35)
    at com.guitarjwindows.starter.Starter$1.run(Starter.java:33)
    at java.lang.Thread.run(Unknown Source)

2015-05-05 13:30:24,505 FATAL Unable to register shutdown hook because JVM is shutting down.
[INFO ] 2015-05-05 13:30:24.515 [Shutdown-thread] WindowsMidiCommunicator - Max receivers:0
[INFO ] 2015-05-05 13:30:24.516 [Shutdown-thread] WindowsMidiCommunicator - 2- Saffire 6USBobtained as inputDevice
[INFO ] 2015-05-05 13:30:24.516 [Shutdown-thread] WindowsMidiCommunicator - Max transmitters:-1
[INFO ] 2015-05-05 13:30:24.516 [Shutdown-thread] WindowsMidiCommunicator - Open receivers:
[INFO ] 2015-05-05 13:30:24.516 [Shutdown-thread] WindowsMidiCommunicator - No default receiver
[INFO ] 2015-05-05 13:30:24.516 [Shutdown-thread] WindowsMidiCommunicator - Open transmitters:
[INFO ] 2015-05-05 13:30:24.517 [Shutdown-thread] WindowsMidiCommunicator - Default transmitter: com.sun.media.sound.MidiInDevice$MidiInTransmitter@151107e
[INFO ] 2015-05-05 13:30:24.517 [Shutdown-thread] WindowsMidiCommunicator - Open transmitters now:
[INFO ] 2015-05-05 13:30:24.517 [Shutdown-thread] WindowsMidiCommunicator - com.sun.media.sound.MidiInDevice$MidiInTransmitter@151107e
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - Max receivers:-1
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - 2- Saffire 6USBobtained as outputDevice
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - Max transmitters:0
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - Open receivers:
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - Default receiver: com.sun.media.sound.MidiOutDevice$MidiOutReceiver@1716ab5
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - Open receivers now:
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - com.sun.media.sound.MidiOutDevice$MidiOutReceiver@1716ab5
[INFO ] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - Open transmitters:
[ERROR] 2015-05-05 13:30:24.518 [Shutdown-thread] WindowsMidiCommunicator - No default transmitter
[INFO ] 2015-05-05 13:30:24.571 [Shutdown-thread] WindowsMidiCommunicator - outputDevice closed
[INFO ] 2015-05-05 13:30:24.572 [Shutdown-thread] WindowsMidiCommunicator - inputDevice closed
2015-05-05 13:30:24,599 FATAL Unable to register shutdown hook because JVM is shutting down.
[INFO ] 2015-05-05 13:30:24.600 [Shutdown-thread] Starter$1 - Shutting down log4j2

person Finn    schedule 05.05.2015    source источник
comment
Попробуйте получить состояние LoggerContext и протестировать его перед выключением: (LoggerContext)LogManager.getContext().getState()   -  person jMounir    schedule 05.05.2015
comment
Метод @jMounir getState() не существует, как вы предлагаете. это log4j2   -  person Finn    schedule 05.05.2015
comment
Извините, я ошибся, это должно называться так: ((LoggerContext)LogManager.getContext()).getState()   -  person jMounir    schedule 05.05.2015
comment
@jMounir Я добавил его в начало метода запуска. Я получаю состояние = начало. Ошибка, показанная в исходном сообщении, отображается до того, как состояние = начало распечатки.   -  person Finn    schedule 05.05.2015
comment
Куда поставили этот код. потому что я вижу комментарий /** on exit */ вы имеете в виду событие при выходе?. потому что вы не можете зарегистрировать перехватчик выключения, когда программа выполняет выключение. вот что сказано в документации: После начала последовательности выключения невозможно зарегистрировать новый хук выключения или отменить регистрацию ранее зарегистрированного хука. Попытка любой из этих операций вызовет исключение IllegalStateException. из docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html   -  person jMounir    schedule 06.05.2015
comment
@jMounir Я поместил код прямо в основной поток. /** onexit**/ указывает, что это происходит при выходе.   -  person Finn    schedule 06.05.2015


Ответы (1)


Я думаю, что в log4j также есть хук выключения, и порядок выполнения хука Shutdwon определяется JVM, поэтому вы не можете на это повлиять. Я мог бы отключить log4j shutdownhook и выполнить очистку самостоятельно, но, возможно, лучше проверить, что делает log4j.

person HamoriZ    schedule 05.05.2015