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

如何使用Maven将Java 17代码编译为Java 8及更早兼容版本

报错根因

你使用JDK 17作为编译执行环境时,javac原生不支持将语法兼容版本(source)设为17的同时,生成Java 8版本的目标字节码(target)。从JDK 9引入模块化机制后,javac对source版本高于target版本的跨版本编译场景做了跨度限制,这是你触发报错的直接原因。

可行解决方案

分两种场景选择适配方案:

场景1:不需要使用Java 17的新语法,仅本地开发环境为JDK 17,需要输出Java 8兼容产物

直接调整Maven编译配置即可,同时增加参数避免误用到高版本核心类库:

<properties>
    <!-- 限制代码语法仅能使用Java 8及以下的特性 -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <!-- 生成的字节码兼容Java 8及以上版本 -->
    <maven.compiler.target>1.8</maven.compiler.target>
    <!-- 编译时关联Java 8的核心类库,避免编译期通过但运行在Java 8时出现类/方法不存在的错误 -->
    <maven.compiler.release>8</maven.compiler.release>
</properties>

你之前单独使用release参数未解决问题的原因是:release是JDK 9+新增的参数,会同时锁定source、target、核心类库三个版本,如果你指定release=17则自动锁定target为17,自然无法得到Java 8兼容的产物。

场景2:需要使用Java 17的语法特性(如var、文本块、record、instanceof模式匹配等),同时要求产物可在Java 8上运行

原生javac不支持该场景,需要使用第三方编译插件Jabel实现语法转译,配套API兼容性校验的配置如下:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <source>17</source>
                <target>1.8</target>
                <release>8</release>
                <compilerArgs>
                    <arg>--enable-preview</arg>
                    <arg>-Xlint:-preview</arg>
                </compilerArgs>
                <annotationProcessorPaths>
                    <path>
                        <groupId>com.github.bsideup.jabel</groupId>
                        <artifactId>jabel-javac-plugin</artifactId>
                        <version>0.4.2</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
        <!-- 校验代码是否用到Java 8以上的核心类库API,避免运行时报错 -->
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>animal-sniffer-maven-plugin</artifactId>
            <version>1.23</version>
            <executions>
                <execution>
                    <id>check-java8-compatibility</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>check</goal>
                    </goals>
                    <configuration>
                        <signature>
                            <groupId>org.codehaus.mojo.signature</groupId>
                            <artifactId>java18</artifactId>
                            <version>1.0</version>
                        </signature>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

注意:该方案仅支持语法特性的向下兼容,Java 8之后新增的核心类库API(如HttpClient、Stream新增方法等)无法被转译,运行在Java 8环境时会抛出NoClassDefFoundError/NoSuchMethodError异常,所以需要配套animal-sniffer插件做编译期校验。

source与target参数独立设计的原因

两个参数的作用完全独立,不存在必须一致的设计要求:

  • source:限制代码可使用的语法特性版本,超过该版本的语法会在编译期直接报错,和生成的字节码版本无关
  • target:指定最终生成的.class字节码的版本,决定了可运行该产物的最低JRE版本,和代码使用的语法版本无强制绑定

低版本JDK作为编译环境时可以自由跨版本配置,比如用JDK 8编译时,可配置source=1.8、target=1.6,生成能运行在Java 6环境的字节码。仅高版本JDK(9+)对source高于target的跨度做了限制,才会出现你遇到的版本兼容报错,和参数本身的设计无关。你使用的Maven 3.8.3版本完全兼容上述所有配置,无需调整Maven版本。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:54:05