Diagnose NoClassDefFoundError during Spring Boot when class is available to ClassLoader

时间:2018-07-25 04:55:03

标签: java spring eclipse maven spring-boot

I have a Java/Maven project (POM-based) which builds and launches fine when using java -jar on the uber JAR produced by my Maven build on the command line, using the spring-boot-maven-plugin:

                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>2.0.3.RELEASE</version>
                    <configuration>
                        <mainClass>com.company.Application</mainClass>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

The JAR is created (~100MB), and launches as expected.

However, I'm unable to launch this same application in Eclipse using the right-click -> Run As -> Java Application configuration on the main class I've defined in my POM. It's a Maven project, and M2E is up-to-date/refreshed, etc.

The error is:

java.lang.NoClassDefFoundError: Could not initialize class org.slf4j.LoggerFactory

So clearly some dependency issues with the logging frameworks. However: My first head-scratcher was, why does this work in Maven using the CLI, and fail in Eclipse using M2E?

So I went and looked at the classpaths, and they seem identical. (Looking at the Maven Dependencies list in Eclipse, and the BOOT-INF directory contained in my uber JAR.) The interesting bits are:

slf4j-api        1.7.25
log4j-over-slf4j 1.7.25
logback-core     1.2.3
logback-classic  1.2.3
commons-logging  1.1.3

So, I debugged. I placed a breakpoint on NoClassDefFoundError, and captured this. Note that the debugger is paused on the thrown exception, and the watch expression in the upper-right is getClass().getClassLoader().classes, which is a Vector.

How is it possible that we're throwing on LoggerFactory, even though this very class is present in the current ClassLoader? Where should I look next?

enter image description here

Edit: Since it's causing some confusion, the class in which Eclipse has caught this error (Category.java) is not one of my classes. It's inside a dependency (see Eclipse titlebar) and as a result cannot be modified.

0 个答案:

没有答案