Description
Tomcat calls Logger.isEnabled at the beginning of its ClassLoader#loadClass implementation.
If the method requires to load additional classes (e.g. org.apache.logging.log4j.core.Filter.Result) an infinite recursion occurs.
Reproduction
- configure Tomcat to use Log4j 2.x as server's logging framework,
- add a Spring Boot 3 application without Log4j2 jars,
- a stack overflow occurs.
Details
This issue was first reported in this StackOverflow question.
The problem occurs because:
- If no logger context exists for a given classloader and
configLocation == null the ClassLoaderContextSelector returns the logger context for the parent classloader. This is what happens in most LogManager.getContext calls;
- Spring Boot adds a class from the webapp classloader as global filter to the logger context's configuration;
- Tomcat calls
Logger.isEnabled at the beginning of ClassLoader#loadClass hence it triggers the loading of all classes used by the global filter. This process uses the webapp classloader, hence the recursion.
Description
Tomcat calls
Logger.isEnabledat the beginning of itsClassLoader#loadClassimplementation.If the method requires to load additional classes (e.g.
org.apache.logging.log4j.core.Filter.Result) an infinite recursion occurs.Reproduction
Details
This issue was first reported in this StackOverflow question.
The problem occurs because:
configLocation == nulltheClassLoaderContextSelectorreturns the logger context for the parent classloader. This is what happens in mostLogManager.getContextcalls;Logger.isEnabledat the beginning ofClassLoader#loadClasshence it triggers the loading of all classes used by the global filter. This process uses the webapp classloader, hence the recursion.