Dave Dority created LOGGING-192:
-----------------------------------
Summary: NoClassDefFoundError:
org/apache/logging/log4j/spi/LoggerAdapter when using custom classloader
Key: LOGGING-192
URL: https://issues.apache.org/jira/browse/LOGGING-192
Project: Commons Logging
Issue Type: Bug
Affects Versions: 1.3.2, 1.3.1, 1.3.0
Environment: This behavior was observed while running Adopt Open JDK
11 and the latest version of Tomcat 9. The behavior can be reproduced outside
of tomcat (see attached reproduction case).
Reporter: Dave Dority
Fix For: 2.0, 1.3.3
Attachments: commons-logging-classloading-issue.zip
If you have:
* A web application running in Tomcat which contains commons-logging:1.2
* That web application contains a custom classloader for loading a seperately
distributed software component (whose dependencies will conflict with the
dependencies of the web application).
* The software component uses commons-logging:1.3.2
When the web application attempts use software component, the code
[here|https://github.com/apache/commons-logging/blob/rel/commons-logging-1.3.2/src/main/java/org/apache/commons/logging/LogFactory.java#L918-L938]
looks for the presence of different logging implementation classes on the
thread context classloader's (TCCL) classpath to select an optimal
implementation. It seems like what is happening is that the LogFactory class
looking for implementation class on the TCCL's classpath and the trying to load
the selected factory from the web application's custom classloader (the loader
for the instance of LogFactory that is running). This is the result:
{code:java}
Exception in thread "main" java.lang.NoClassDefFoundError:
org/apache/logging/log4j/spi/LoggerAdapter
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at
org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:419)
at
org.apache.commons.logging.LogFactory.lambda$newFactory$3(LogFactory.java:1431)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at
org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:1431)
at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:928)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:987)
at
org.component.ClassLoadedComponent.<clinit>(ClassLoadedComponent.java:7)
at
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at
java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at
java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.lang.Class.newInstance(Class.java:584){code}
This occurs when the web application has commons-logging:1.2 and the software
component has commons-logging:1.3.x. This does not occur when both are using
version 1.2.
Unfortunately, changing the web application's version of commons-logging is
outside is not something I can influence.
An isolated reproduction case is attached. It requires Java 11. To run it:
* Unzip it to a directory.
* Run
{code:java}
./gradlew reproduceIssue{code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)