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

Spring Boot多发布版本Jar使用Java 11运行出现ClassNotFoundException

问题描述

我尝试在不同Java版本(默认Java 8和Java 11)环境下运行包含多发布版本Jar的Spring Boot应用
项目使用Java 8运行完全正常,但切换到Java 11运行时抛出ClassNotFoundException异常

项目结构

项目结构

pom.xml配置

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.5</version>
    <relativePath/> 
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
    <java.version>1.8</java.version>
    <start.class>com.example.demo.DemoApplication</start.class>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.inq</groupId>
        <artifactId>touchsocial-stress-testing</artifactId>
        <version>4.0-SNAPSHOT</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-toolchains-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <toolchains>
                    <jdk>
                        <version>zulu-11</version>
                    </jdk>
                </toolchains>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>toolchain</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <executions>
                <execution>
                    <id>default-compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <release>8</release>
                    </configuration>
                </execution>
                <execution>
                    <id>compile-java-11</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <release>11</release>
                        <compileSourceRoots>
                            <compileSourceRoot>${project.basedir}/src/main/java</compileSourceRoot>
                        </compileSourceRoots>
                        <multiReleaseOutput>true</multiReleaseOutput>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <archive>
                    <manifestEntries>
                        <Multi-Release>true</Multi-Release>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>${start.class}</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

现象说明

添加<start-class>配置后构建成功,但使用Java 11运行打好的Jar包时依然抛出ClassNotFoundException
Java11运行报错截图
使用配置了Java 8的JAVA_HOME环境运行则一切正常
Java8正常运行截图

注:出于POC验证目的,两个DemoApplication.java文件的内容完全一致


解决方案

该问题的核心原因是Spring Boot 2.x默认的重打包逻辑没有透传多版本Jar的配置,且其类加载器对嵌套Fat Jar的多版本特性支持存在兼容问题,按以下步骤修改即可解决:

  1. 透传多版本Jar标记到Spring Boot Fat Jar
    修改spring-boot-maven-plugin配置,增加manifest入口声明该Jar为多发布版本Jar,配置如下:
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <mainClass>${start.class}</mainClass>
        <archive>
            <manifestEntries>
                <Multi-Release>true</Multi-Release>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>
  1. 修正Java 11源码目录配置
    你当前配置的Java11编译源目录和Java8共用src/main/java,会导致重复编译覆盖类。建议单独创建Java11专属源码目录src/main/java11,将Java11版本的类放入该目录,再修改maven-compiler-plugin的compile-java-11执行配置:
<configuration>
    <release>11</release>
    <compileSourceRoots>
        <compileSourceRoot>${project.basedir}/src/main/java11</compileSourceRoot>
    </compileSourceRoots>
    <multiReleaseOutput>true</multiReleaseOutput>
</configuration>
  1. 添加JVM启动参数(针对Java 11兼容问题)
    运行Java11环境下的Jar包时,增加启动参数强制开启多版本Jar识别:
java -Djava.util.jar.JarFile.metaInfVersions=true -jar demo-0.0.1-SNAPSHOT.jar
  1. 验证配置生效
    打包完成后解压Fat Jar,确认两个配置存在:
  • META-INF/MANIFEST.MF文件中有Multi-Release: true配置项
  • BOOT-INF/classes/META-INF/versions/11/路径下存在对应版本的类文件

内容的提问来源于stack exchange,提问作者utkarsh jha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:15:02