一次搞懂:Gradle 运行时 JDK 与项目 compileOptions 中的 Java 版本有什么区别?

前言

在开发 Android 应用时,不少开发者都遇到过这样一个诡异的错误:

text

Unsupported class file major version 64

明明自己在build.gradle中写的compileOptions是 Java 8,可为什么 Gradle 非要报一个 Java 20 的错误?两者之间到底有什么关系?

今天我们就来彻底理清这两个“Java 版本”的区别,并解决由此引发的构建失败问题。

一、两个“Java 版本”的概念

在 Android 项目中,存在两个完全不同的 Java 版本概念:

1. Gradle 运行时 JDK 版本

  • 它是什么?
    Gradle 本身是用 Java 编写的构建工具。当你执行./gradlew build时,Gradle 会启动一个 Java 进程来完成构建工作。这个进程所使用的 JDK 版本,就是Gradle 运行时 JDK 版本

  • 如何查看?
    在项目根目录下运行:
    ./gradlew --version
    输出的第一行JVM后面的版本号就是这个值。

  • 它决定什么?
    决定了 Gradle 能否正常启动。如果 Gradle 版本太老,不支持当前 JDK 版本(比如 Gradle 7.0.2 不支持 Java 20),就会直接报错退出。

2. 项目的compileOptions中的 Java 版本

  • 它是什么?
    在模块的build.gradle文件中,通过compileOptions配置的sourceCompatibilitytargetCompatibility,用于指定项目源代码的语言级别以及生成的字节码兼容的最低 Java 版本

  • 示例配置:

    android { compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
  • 它决定什么?
    决定了你可以使用哪些 Java 语法特性(如 Lambda、Stream API),以及生成的字节码能在多老的 JVM 上运行。它完全不控制Gradle 运行时使用的 JDK 版本。

二、两者之间的关系

简单说:没有直接关系。

  • Gradle 运行时 JDK 是工人手里的机器—— 它只需要满足 Gradle 版本的要求即可。

  • 项目的compileOptions产品规格书—— 它规定最终 APK 内的代码兼容级别。

你完全可以:

  • 用 JDK 17 运行 Gradle

  • 但要求编译出的代码兼容 Java 8

这是完全合法且常见的做法。反之,即使你设置了sourceCompatibility = 1.8,如果你用 Java 20 去运行一个老旧的 Gradle 7.0.2,依然会崩溃,因为Gradle 自身不认 Java 20

三、常见错误场景

错误现象根本原因
Unsupported class file major version 64Gradle 运行时 JDK 是 Java 20(major 64),而当前 Gradle 版本(如 7.0.2)最高只支持到 Java 17。
Unsupported class file major version 61运行时 JDK 是 Java 17,但 Gradle 版本太老(如 6.x)。
编译时提示 Lambda 表达式不支持sourceCompatibility未设置为 1.8 或更高。

四、如何解决?

方案一:降低 Gradle 运行时 JDK 版本(推荐,改动最小)

  1. 在 Android Studio 中,点击FileProject StructureSDK Location

  2. Gradle Settings部分,将Gradle JDK改为JDK 11JDK 17

  3. 点击OK,然后重新同步项目。

注意:JDK 17 是目前最稳妥的选择,Gradle 7.x 和 8.x 都完美支持。

方案二:升级 Gradle 版本(如果必须使用高版本 JDK)

如果因为某些原因(例如团队统一要求)你非要用 Java 20 来运行 Gradle,那么就需要升级 Gradle 到支持 Java 20 的版本。

Gradle 版本最高支持 Java 版本
7.0 ~ 7.4Java 17
7.5 ~ 7.6.xJava 19
8.3+Java 20

修改gradle/wrapper/gradle-wrapper.properties

properties

distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip

然后同步项目。

注意:从 Gradle 7.x 升级到 8.x 可能会遇到其他废弃 API 的兼容问题,需要额外处理。

五、总结

  • Gradle 运行时 JDK:负责启动 Gradle 进程,其版本必须被 Gradle 版本所支持。

  • compileOptions中的 Java 版本:只影响项目源码的编译规则和字节码兼容性,与 Gradle 运行时无关。

  • 最佳实践

    • 将 Gradle JDK 设置为JDK 17(稳定且广泛支持)。

    • compileOptions设置为JavaVersion.VERSION_1_8(兼容绝大多数 Android 设备)。

    • 如果确实需要 Java 11/17 的语言特性,再相应升级sourceCompatibility,同时确保minSdkVersion足够高。

希望这篇文章能帮你彻底厘清这两个容易混淆的 Java 版本概念,从此不再被Unsupported major version所困扰。


如果你有更多关于 Android 构建配置的问题,欢迎在评论区留言讨论。