In case it's helpful, I thought I would share our code which triggers this. Perhaps there is a different, thread-safe way to re-initialize logback on a running system that I just don't know about?
{noformat}
public void reconfigureLogback(URL logbackFile) {
//Assume SLF4J is bound to logback in the current environment
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
//Clear any previous configuration (e.g. the default)
context.reset();
//Add the application specific properties to the context so that they can be referenced in the logback configuration
Properties extraProperties = getApplicationProperties();
for (Map.Entry<Object, Object> entry : extraProperties.entrySet()) {
// ******** BEGIN FAILURE ********
// This call fails intermittently with a java.util.ConcurrentModificationException
// This is caused because LoggerContext.putProperty() called LoggerContext.syncRemoteView which
// iterates through the LoggerContext.loggerCache. Simultaneously, other threads are still calling
// LoggerContext.getLogger() which can modify the LoggerContext.loggerCache
{noformat}
public void reconfigureLogback(URL logbackFile) {
//Assume SLF4J is bound to logback in the current environment
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(context);
//Clear any previous configuration (e.g. the default)
context.reset();
//Add the application specific properties to the context so that they can be referenced in the logback configuration
Properties extraProperties = getApplicationProperties();
for (Map.Entry<Object, Object> entry : extraProperties.entrySet()) {
// ******** BEGIN FAILURE ********
// This call fails intermittently with a java.util.ConcurrentModificationException
// This is caused because LoggerContext.putProperty() called LoggerContext.syncRemoteView which
// iterates through the LoggerContext.loggerCache. Simultaneously, other threads are still calling
// LoggerContext.getLogger() which can modify the LoggerContext.loggerCache
context.putProperty((String) entry.getKey(), (String) entry.getValue());
// ******** END FAILURE ********
}
//Reconfigure logback with the new configuration file
configurator.doConfigure(logbackFile);
}
{noformat}