How to get rid of log4j message warning about "no appenders" at multi-thread application shutdown?

StackOverflow https://stackoverflow.com/questions/16168304

Вопрос

I have a multi-thread program which basically has two infinite loop threads plus some GUI (Swing). My two infinite loop threads have their own log4j loggers like this:

    static final Category LOG = Category.getInstance(RReceiver.class);

When in GUI I detect exit key I just do System.exit(0):

public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getKeyCode()!=27 && e.getKeyCode()!=KeyEvent.VK_BACK_SPACE) return false; 
    System.exit(0);
    return true;
}

The effect in console is like this:

DEBUG 13:07:00,940 [ Receiver] (RReceiver.java:93) - got response len:38
DEBUG 13:07:01,044 [ Receiver] (RReceiver.java:93) - got response len:38
DEBUG 13:07:01,045 [ Receiver] (RReceiver.java:93) - new status dev 4
log4j:WARN No appenders could be found for logger (com.normantech.ibcol.radiobox.RReceiver).
log4j:WARN Please initialize the log4j system properly.

The warning is not appearing always. I suspect there's wrong deinitialisation sequence, but can't figure it out. Why is that happening? I've tried to use LogManager.shutdown(); but it didn't help. I tried to finish my infinite loops nicely, but it's not best solution, because I I needed to put some additional Thread.sleep(x), tried different x, and actually was not sure if this helped.

Это было полезно?

Решение

The core problem is that you're killing your threads by calling System.exit(), rather than having them shutdown cleanly. This means they may keep running very briefly after everything else is closed but before the JVM actually ends the process, and if they use any shared state during that time (e.g. the logging system), it could be in an inconsistent or broken state as it may have been shutdown. This is not good practice (see http://www.javapractices.com/topic/TopicAction.do?Id=86).

The way to solve this is to properly shutdown your threads before shutting down shared resources (the logging system). Instead of just calling system.exit(), tell each thread that it's time to stop, and wait from them to do so. The cleanest way to do this is to have them check a running boolean on each loop, and to set that boolean to false externally when you want the loop to stop. You can then wait for the thread to notice this boolean and terminate by calling Thread.join() on the given thread instance, or by having the thread set some finished boolean when it's done (best to mark both these booleans as volatile).

If each iteration of your loop takes sometime, or contains wait() or sleep() calls you should look at checking the running boolean more often during the loop, or using Thread.interrupt().

Once this has finished and you're sure every other thread has stopped, you can then call LogManager.shutdown() and actually terminate your process.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top