My application is throwing ConcurrentModificationException when it is trying to exit the program.It is using a standard Logback configuration. This works fine when running as a standalone java application but throws the exception when trying to run inside a docker container. The stack trace is as below:
Exception in thread "Logback shutdown hook [default]" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
at ch.qos.logback.classic.LoggerContext.fireOnReset(LoggerContext.java:323)
at ch.qos.logback.classic.LoggerContext.reset(LoggerContext.java:226)
at ch.qos.logback.classic.LoggerContext.stop(LoggerContext.java:348)
at ch.qos.logback.core.hook.ShutdownHookBase.stop(ShutdownHookBase.java:39)
at ch.qos.logback.core.hook.DelayingShutdownHook.run(DelayingShutdownHook.java:57)
at java.base/java.lang.Thread.run(Thread.java:834)
I am using a standard Logback configuration file through logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--See https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html -->
<shutdownHook
class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE_JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<!-- <prettyPrint>true</prettyPrint> -->
</jsonFormatter>
<timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSXXX</timestampFormat>
<includeContextName>false</includeContextName>
<appendLineSeparator>true</appendLineSeparator>
</layout>
<charset>UTF-8</charset>
</encoder>
</appender>
<appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>5000</queueSize> <!-- Default is 256 -->
<discardingThreshold>0</discardingThreshold> <!-- Instruction to drop events
once the buffer reaches the max capacity. Default value is 20%.
20 means drop lower event when has 20% capacity remaining -->
<neverBlock>true</neverBlock><!-- default false. Setting it to true to
cause the Appender not block the application and just drop the messages -->
<maxFlushTime>5000</maxFlushTime> <!-- The default maximum queue flush time allowed during appender stop. If
the worker takes longer than this time it will exit, discarding any remaining
cartItems in the queue -->
<appender-ref ref="CONSOLE_JSON"/>
</appender>
<logger name="org.springframework.web" level="INFO"/>
<root level="INFO">
<appender-ref ref="ASYNCSTDOUT"/>
</root>
</configuration>
The artifacts I am using in my pom are as below:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.8</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.14</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-jackson</artifactId>
<version>0.1.5</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.contrib</groupId>
<artifactId>logback-json-classic</artifactId>
<version>0.1.5</version>
</dependency>
</dependencies>