You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Maven构建可执行Shaded Jar遇JavaLoggingSystem类找不到异常求助

问题描述

我通过Maven创建了一个包含所有依赖的可执行Shaded Jar,想要用命令java -jar integration-tests.jar启动,但执行时抛出了如下异常:

Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) Caused by: java.lang.IllegalStateException: java.lang.ClassNotFoundException: org.springframework.boot.logging.java.JavaLoggingSystem at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:130) at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:117) at com.ciscospark.integration.JUnitTestRunner.main(JUnitTestRunner.java:41) ... 8 more Caused by: java.lang.ClassNotFoundException: org.springframework.boot.logging.java.JavaLoggingSystem at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at org.springframework.util.ClassUtils.forName(ClassUtils.java:250) at org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:125) ... 10 more

奇怪的是,解压integration-tests.jar后,在extracted/BOOT-INF/lib/spring-boot-1.4.7.RELEASE.jar中确实能找到./org/springframework/boot/logging/java/JavaLoggingSystem.class文件。

附上我的Maven配置:

<build> 
  <finalName>integration-tests</finalName> 
  <plugins> 
    <plugin> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-maven-plugin</artifactId> 
      <configuration> 
        <mainClass>com.integration.JUnitTestRunner</mainClass> 
        <finalName>integration-tests</finalName> 
      </configuration> 
      <executions> 
        <execution> 
          <goals> 
            <goal>repackage</goal> 
          </goals> 
        </execution> 
      </executions> 
    </plugin> 
    <plugin> 
      <artifactId>maven-failsafe-plugin</artifactId> 
      <version>2.20.1</version> 
      <configuration> 
        <testClassesDirectory>${project.build.outputDirectory}</testClassesDirectory> 
        <testSourceDirectory>${project.build.sourceDirectory}</testSourceDirectory> 
      </configuration> 
      <executions> 
        <execution> 
          <id>integration-tests</id> 
          <goals> 
            <goal>integration-test</goal> 
            <goal>verify</goal> 
          </goals> 
        </execution> 
      </executions> 
    </plugin> 
    <plugin> 
      <groupId>org.codehaus.cargo</groupId> 
      <artifactId>cargo-maven2-plugin</artifactId> 
      <version>1.6.2</version> 
      <configuration> 
        <container> 
          <containerId>tomcat7x</containerId> 
        </container> 
        <configuration> 
          <type>standalone</type> 
          <properties> 
            <cargo.servlet.port>${tomcat.server.port}</cargo.servlet.port> 
            <cargo.rmi.port>${tomcat.rmi.port}</cargo.rmi.port> 
            <cargo.tomcat.ajp.port>${tomcat.ajp.port}</cargo.tomcat.ajp.port> 
          </properties> 
        </configuration> 
        <deployables> 
          <deployable> 
            <groupId>com.me</groupId> 
            <artifactId>my-server</artifactId> 
            <type>war</type> 
            <properties> 
              <context>/</context> 
            </properties> 
            <pingUrlPath>/ping</pingUrlPath> 
          </deployable> 
        </deployables> 
      </configuration> 
      <executions> 
        <execution> 
          <id>start-server</id> 
          <phase>pre-integration-test</phase> 
          <goals> 
            <goal>start</goal> 
          </goals> 
        </execution> 
        <execution> 
          <id>stop-server</id> 
          <phase>post-integration-test</phase> 
          <goals> 
            <goal>stop</goal> 
          </goals> 
        </execution> 
      </executions> 
    </plugin> 
  </plugins> 
</build>

请问我哪里操作出错了?


问题分析与解决方案

这个问题的核心是Spring Boot的类加载机制和你当前的Jar构建方式不匹配,同时还有一个容易忽略的细节问题,下面逐一拆解:

1. 先揪出最明显的错误:主类包名不一致

你在Maven配置里指定的主类是com.integration.JUnitTestRunner,但异常栈里显示的类路径是com.ciscospark.integration.JUnitTestRunner,包名差了ciscospark这一截!这会导致Spring Boot加载时找不到正确的主类,间接引发后续的类加载异常,先把这个包名修正一致再说。

2. 混淆了Spring Boot Repackage和Shade打包的区别

你提到要构建"包含所有依赖的Shaded Jar",但当前用的是spring-boot-maven-plugin的repackage目标——这个插件生成的是Spring Boot专属的可执行Jar,它把依赖放在BOOT-INF/lib下,并且用Spring自己的JarLauncher来加载类。如果你的JUnitTestRunner没有通过Spring Boot的标准启动流程初始化,直接调用Spring的LoggingSystem类,就会因为类加载器未完全初始化,找不到嵌套Jar里的类。

针对场景的修复方案

方案一:按Spring Boot标准流程启动(推荐)

把你的JUnitTestRunner改成标准的Spring Boot应用类,让Spring负责初始化类加载器:

@SpringBootApplication
public class JUnitTestRunner implements CommandLineRunner {
    public static void main(String[] args) {
        // 让Spring Boot完整初始化上下文
        SpringApplication.run(JUnitTestRunner.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // 在这里执行你的集成测试逻辑
    }
}

这样Spring Boot会正确加载BOOT-INF/lib下的所有依赖类,包括JavaLoggingSystem。

方案二:用maven-shade-plugin构建真正的Shaded Jar

如果你不需要Spring Boot的特性,只是想要一个包含所有依赖的普通可执行Jar,那就改用maven-shade-plugin,同时移除spring-boot-maven-plugin的repackage执行:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.4</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <!-- 这里要填正确的主类全路径 -->
                        <mainClass>com.ciscospark.integration.JUnitTestRunner</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

这个插件会把所有依赖类合并到同一个Jar里,用JDK标准的类加载器就能加载所有类。


内容的提问来源于stack exchange,提问作者Shane Gannon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:33:49