Reported by RV-Predict (a dynamic race detector) when running the test suite: Data race on field org.apache.catalina.core.ApplicationFilterFactory.factory: {{{ Concurrent read in thread T27 (locks held: {Monitor@3bb9edae}) ----> at org.apache.catalina.core.ApplicationFilterFactory.getInstance(ApplicationFilterFactory.java:54) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:182) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:277) - locked Monitor@3bb9edae at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:259) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) T27 is created by T15 at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:1010) Concurrent write in thread T28 (locks held: {Monitor@6d627e28}) ----> at org.apache.catalina.core.ApplicationFilterFactory.getInstance(ApplicationFilterFactory.java:55) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:182) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:277) - locked Monitor@6d627e28 at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:259) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) T28 is created by T15 at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:1010) }}} Another non-thread-safe implementation of lazy initialization.
I've simplified the code in trunk but I'm not yet convinced that this race condition will trigger anything worse than the creation of multiple ApplicationFilterFactory instances where the additional instances will quickly become eligible for GC.
I am now convinced that there is a rare/unlikely issue here. It has been fixed in 8.0.x for 8.0.27 onwards.