Uploaded image for project: 'Commons Logging'
  1. Commons Logging
  2. LOGGING-192

NoClassDefFoundError: org/apache/logging/log4j/spi/LoggerAdapter when using custom classloader

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 1.3.0, 1.3.1, 1.3.2
    • 1.3.4
    • None
    • 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).

    • Important

    Description

      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 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:

      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)

      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 
        ./gradlew reproduceIssue

          

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              misterdorito Dave Dority
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: