org.apache.log4j.helpers.AppenderAttachableImpl utilizes a java.util.Vector for internal storage, but at least in "removeAllAppenders()" additional synchronization is needed. We've got an integration test (part of a bigger setup) where we get reproducible an ArrayIndexOutOfBoundsException (see below). Perhaps there is an issue with the test case (i.e. multiple calls to org.apache.log4j.PropertyConfigurator.configureAndWatch(..)) but this should be handled gracefully. This is the exception we get: java.lang.ArrayIndexOutOfBoundsException: 1 >= 1 at java.util.Vector.elementAt(Vector.java:470) at org.apache.log4j.helpers.AppenderAttachableImpl.removeAllAppenders(AppenderAttachableImpl.java:139) at org.apache.log4j.Category.removeAllAppenders(Category.java:868) at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:603) at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:509) at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:415) at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:316) at org.apache.log4j.PropertyWatchdog.doOnChange(PropertyConfigurator.java:682) at org.apache.log4j.helpers.FileWatchdog.checkAndConfigure(FileWatchdog.java:88) at org.apache.log4j.helpers.FileWatchdog.<init>(FileWatchdog.java:57) at org.apache.log4j.PropertyWatchdog.<init>(PropertyConfigurator.java:674) at org.apache.log4j.PropertyConfigurator.configureAndWatch(PropertyConfigurator.java:382) at de.espirit.firstspirit.server.logging.LoggingManagerImpl.init(LoggingManagerImpl.java:118) at de.espirit.firstspirit.server.AbstractManagerHost.addManager(AbstractManagerHost.java:99) at de.espirit.firstspirit.server.MockManagerHost.getManager(MockManagerHost.java:177) at de.espirit.firstspirit.server.MockManagerHost.getManager(MockManagerHost.java:166) at de.espirit.firstspirit.server.ServerTestCase.getManager(ServerTestCase.java:251) at de.espirit.firstspirit.server.ServerTestCase.setUp(ServerTestCase.java:175) at de.espirit.firstspirit.io.servlet.TestRemoteLoggingDispatcher.setUp(TestRemoteLoggingDispatcher.java:48) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722)
This is one area where I've long since been patching log4j -- so that I can use a CopyOnWriteArrayList and avoid synchronization in this area, most especially on callAppenders().
I agree, using CopyOnWriteArrayList and iterator() would be the easiest fix. Is compatibility to JDK5 or lower still a prerequisite?