As claimed in the FAQ, log4j is thread safe, but this method, copied from org.apache.log4j.Category is not thread safe: /** Starting from this category, search the category hierarchy for a non-null level and return it. Otherwise, return the level of the root category. <p>The Category class is designed so that this method executes as quickly as possible. */ public Level getEffectiveLevel() { for(Category c = this; c != null; c=c.parent) { if(c.level != null) return c.level; } return null; // If reached will cause an NullPointerException. } This method can cause NPE. A configuration that recreates it: define in log4j.xml logger level for com.traffix: <logger name="com.traffix"> <level value="ALL"/> </logger> and define log level for com.traffix.session: <logger name="com.traffix.session"> <level value="ALL"/> </logger> run code that uses com.traffix.session loggers. now delete the com.traffix.session definition from the log4j.xml. It is possible to encounter this scenario with 2 threads: 1. user logs something using com.traffix.session logger. 2. Thread1 evaluate the if clause: c.level indeed not null. 3. the thread that listens to the file, thread2 changes the log level of c to null because com.traffix.session was deleted from the file by the user. 4. thread1 continues and return c.level which is null. Then we get NPE in Priority.isGreaterOrEqual method because the given priority is null: 2012-10-16 09:29:33,981 WARN java.lang.NullPointerException at org.apache.log4j.Priority.isGreaterOrEqual(Priority.java:123) at org.apache.log4j.Category.isEnabledFor(Category.java:751) at com.traffix.openblox.core.utils.logging.LoggingUtils.isLoggable(LoggingUtils.java:169) at com.traffix.openblox.core.utils.logging.LoggingUtils.doLog(LoggingUtils.java:306) at com.traffix.openblox.core.utils.logging.LoggingUtils.trace(LoggingUtils.java:41) at com.traffix.openblox.core.session.SessionImpl.isPersistSessionData(SessionImpl.java:805)