执行gradle的Java版本配置

介绍

Gradle 是用Java语言编写的工具​,所以运行Gradle必须要有JDK环境,如果电脑上装有多个不同版本的JDK,那运行Gradle时默认会使用哪一个呢?

查看Gradle版本以及内置的其它工具的版本

在Android Studio中创建一个项目,然后打开Android Studio中的Terminal面板,并执行.\gradlew -v命令,效果如下:

PS E:\11_Workspace\01_AndroidStudio\JavaVersionTest> .\gradlew -v          

------------------------------------------------------------
Gradle 8.11.1
------------------------------------------------------------

Build time:    2024-11-20 16:56:46 UTC
Revision:      481cb05a490e0ef9f8620f7873b83bd8a72e7c39

Kotlin:        2.0.20
Groovy:        3.0.22
Ant:           Apache Ant(TM) version 1.10.14 compiled on August 16 2023
Launcher JVM:  11.0.12 (Oracle Corporation 11.0.12+8-LTS-237)
Daemon JVM:    C:\Program Files\Java\jdk-11.0.12 (no JDK specified, using current Java home)
OS:            Windows 10 10.0 amd64

从结果中可以看到如下信息:

  • Gradle使用的版本是8.11.1,它是由/gradle/wrapper/gradle-wrapper.properties中的distributionUrl指定的。
  • Gradle内置Kotlin版本是2.0.20,用于编译由Kotlin语言编写的build.gradle.kts文件。
  • Gradle内置Groovy版本是3.0.22,用于编译由Groovy语言编写的build.gradle文件。
  • Gradle内置Ant版本是1.10.14
    • 用于兼容 Apache Ant 的任务系统,比如构建脚本(build.gradle)中调用了 Ant 任务(如 ant.copyant.jar),Gradle 会通过其内置的 Ant 引擎执行这些操作。
    • 对从 AntMaven 迁移到 Gradle 的项目,Gradle 允许直接调用 Ant 的构建脚本(如 build.xml)。内置 Ant 版本确保这些遗留脚本在 Gradle 环境中正常运行。
    • 部分 Gradle 插件(如 Java 编译、资源处理)在底层仍依赖 Ant 的库实现功能。Ant 版本直接影响这些基础操作的稳定性。
  • Launcher JVM的版本是11.0.12
  • Daemon JVM的版本是11.0.12。且提示说没有指定JDK,当前使用的是JAVA_HOME环境变量中的JDK版本。

Launcher JVM 与 Daemon JVM 的区别

  1. Launcher JVM(启动器 JVM)​

    • 作用:当执行gradlew命令时,系统会启动一个​​临时JVM进程​​(即Launcher JVM),该进程仅负责:
      • 解析命令行参数 (如-v、build等);
      • 检查是否存在​​兼容且空闲的守护进程​​,若不存在则创建一个守护进程,存在则复用这个守护进程,将构建任务委托给守护进程,自身立即退出。
    • 生命周期​​:
      • 仅在执行 Gradle 命令时短暂存在(如执行 ./gradlew -v)。
      • 完成任务后立即退出,不参与实际构建过程。
    • 配置依赖​​:使用当前终端环境变量 JAVA_HOME,如果没有JAVA_HOME则使用系统默认 JDK
  2. Daemon JVM(守护进程 JVM)​

    • 作用:长期运行的后台进程,负责实际执行构建任务(如编译、测试、打包)
    • 生命周期​​:
      • 首次构建时创建​​:若当前无兼容的守护进程(如JDK版本、JVM参数不匹配),Launcher JVM会​​创建并启动新的守护进程​​,该进程长期驻留内存;
      • ​​复用机制​​:后续构建任务如果兼容则会​​直接复用​​已存在的守护进程,避免重复启动开销;
      • ​​生命周期​​:默认闲置3小时后自动终止,或通过gradlew --stop手动停止。
    • 配置依赖​​:
      • 优先读取项目配置(gradle.properties 中的 org.gradle.java.home)。
      • 若未指定,则使用与 Launcher JVM 一样的 JDK。
      • 关键风险​​:若未显式配置,可能因环境变化导致构建 JDK 版本不稳定。因为不同的电脑配置的JAVA_HOME或默认JDK很有可能是不一样的。所以最好在gradle.properties中通过 org.gradle.java.home指定JDK版本。
      • 一张图描述守护进程的复用(这里没有画出Launcher JVM进程):
        在这里插入图片描述
      • 守护进程优点:
        • 启动加速​​:避免每次构建重复加载Gradle核心库(约节省1-4秒);
        • 运行时优化​​:守护进程的热编译机制(如JIT优化)使后续构建速度提升15%-75%;
        • ​​缓存复用​​:项目结构、任务依赖等数据常驻内存,减少重复解析。
        • ​​JDK隔离​​:不同JDK版本会启动独立的守护进程(如Java 11与Java 17各一个);
        • ​​参数隔离​​:JVM内存设置(-Xmx)、系统属性(如file.encoding)等不一致时会创建新进程。
        • 通过–no-daemon可强制禁用守护进程(调试时推荐)。
        • 守护进程默认开启​​(Gradle 3.0+已默认启用)
  3. 为什么要有这两种不同的进程

    • Gradle的运行依赖于Java运行环境,这肯定是依赖于系统的JAVA_HOME或默认安装的JDK,假如你安装了多个JDKGradle无法知道你要用哪一个JDK,所以只能用JAVA_HOME指定的,如果没有设置JAVA_HOME那就只能用PATH环境变量中能找到的那个(即默认JDK)。
    • Gradle运行起来后,它才能去读取gradle.properties文件中的org.gradle.java.home属性,然后才能用该属性指定的JDK版本再启动一个Gradle Daemon
  4. 总结

    • Launcher JVM​​ 是“临时工”,负责点火启动;​​Daemon JVM​​ 是“长期工”,负责高效执行任务。
    • 最佳实践​​:始终在 gradle.properties 中显式配置 org.gradle.java.home,确保构建环境稳定可控。

Android Studio运行Gradle的JDK版本

Android Studio中,运行Gradle使用的JDK版本由:Settings > Build, Execution, Deployment > Build Tools > Gradle > Gradle JDK指定,即使gradle.properties 中的 org.gradle.java.home设置有JDK版本,也是会使用Gradle JDK中指定的版本。这一点有点奇怪,因为这个配置是IDE的本地配置,不同电脑上这个配置很有可能不一样,所以很奇怪为什么不直接使用gradle.properties 中的配置,这样可以放到git版本控制,保存确保每个人都用相同的JDK版本。

Android Studio中的Gradle面板中有一个 “Execute Gradle Task” 的按钮,可用于执行Gradle任务,截图如下:
在这里插入图片描述
在右上角中,可以选择执行任务的作用范围,在输入框中,默认就已经输入了gradle 前缀和一个空格,我们只需要在空格后输入任务名称并按回车即可开始执行该任务。

需要注意的是,这个界面只能用于执行Gradle任务,对于命令 ./gradlew -v并没有执行任何的任务,在命令行是可以直接执行的,而在Gradle面板中无法实现相同的功能,比如你在上面截图的输入框中输入 -v ,然后按回车是得不到期望的结果的。

为什么Gradle面板中输入直接显示gradle前缀而不是gradlew前缀,因为gradlew是一个包装器,它的底层其实就是把要运行的任务交给指定版本Gradle的gradle程序来执行的,这个gradle程序是不带w的。

验证Gradle使用的JDK版本

创建一个全新的Android项目,在截止当前最新版本的Android Studio中创建项目时,IDE默认的 Gradle JDK设置的是D:\01_dev\Android\AndroidStudio\jbr,它是JetBrains Runtime 21.0.6,对应JDK 21版本。

我电脑的JAVA_HOME设置的是JDK 11

打开Android Studio的Terminal,然后执行:.\gradlew -v,结果如下:

PS E:\11_Workspace\01_AndroidStudio\JavaVersionTest> .\gradlew -v

------------------------------------------------------------
Gradle 8.11.1
------------------------------------------------------------

Build time:    2024-11-20 16:56:46 UTC
Revision:      481cb05a490e0ef9f8620f7873b83bd8a72e7c39

Kotlin:        2.0.20
Groovy:        3.0.22
Ant:           Apache Ant(TM) version 1.10.14 compiled on August 16 2023
Launcher JVM:  11.0.12 (Oracle Corporation 11.0.12+8-LTS-237)
Daemon JVM:    C:\Program Files\Java\jdk-11.0.12 (no JDK specified, using current Java home)
OS:            Windows 10 10.0 amd64

这里我们主要看Daemon JVM即可,显示使用的是jdk11,且说没有指定JDK,当前使用的是JAVA_HOME

由于在Android Studio的Gradle面板中无法执法类似.\gradlew -v的功能,所以我可以在项目根目录的build.gradle.kts中编写一个任务来打印使用的jdk版本,如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    alias(libs.plugins.android.application) apply false
    alias(libs.plugins.kotlin.android) apply false
}

tasks.register("printVersion") {
    doLast {
        println("Gradle版本: ${gradle.gradleVersion}")
        println("JDK版本: ${JavaVersion.current()}")
    }
}

在Terminal中执行任务: .\gradlew printVersion,运行结果如下:

PS E:\11_Workspace\01_AndroidStudio\JavaVersionTest> .\gradlew printVersion
[Incubating] Problems report is available at: file:///E:/11_Workspace/01_AndroidStudio/JavaVersionTest/build/reports/problems/problems-report.html

FAILURE: Build failed with an exception.

* Where:
Build file 'E:\11_Workspace\01_AndroidStudio\JavaVersionTest\app\build.gradle.kts' line: 1

* What went wrong:
An exception occurred applying plugin request [id: 'com.android.application', version: '8.10.1']
> Failed to apply plugin 'com.android.internal.application'.
   > Android Gradle plugin requires Java 17 to run. You are currently using Java 11.
      Your current JDK is located in C:\Program Files\Java\jdk-11.0.12
      You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.11.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD FAILED in 9s
<-------------> 0% WAITING
> IDLE
PS E:\11_Workspace\01_AndroidStudio\JavaVersionTest>

报错了,提示说AGP 8.10.1插件需要Java 17来运行。为什么执行 .\gradlew -v不报错?因为这个命令并没有执行任何的任务,而 .\gradlew printVersion执行了一个printVersion任务,Gradle需要编译构建文件,而构建文件中需要应用AGP插件,但是当前的JDK又不支持该AGP插件,所以报错了。

修改gradle.properties文件,在最后添加一行:

org.gradle.java.home=C\:\\Program Files\\Java\\jdk-17

再次执行 .\gradlew printVersion,运行结果如下:

PS E:\11_Workspace\01_AndroidStudio\JavaVersionTest> .\gradlew printVersion

> Task :printVersion
Gradle版本: 8.11.1
JDK版本: 17

BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed

可以看到JDK的版本为17。我们再执行 .\gradlew -v,打印的JVM版本如下:

Launcher JVM:  11.0.12 (Oracle Corporation 11.0.12+8-LTS-237)
Daemon JVM:    C:\Program Files\Java\jdk-17 (from org.gradle.java.home)

可以看到Launcher JVM依旧是jdk11,而Daemon JVMjdk17,而我们自定义的printVersion打印的jdk也是17,这也充分说明我们任务运行的时候是交给Daemon JVM进程执行的,所以打印的是17而不是11。

在Android Studio的Gradle面板中执行printVersion任务,结果如下:

18:05:11: Executing 'printVersion'…

Executing tasks: [printVersion] in project E:\11_Workspace\01_AndroidStudio\JavaVersionTest


> Task :printVersion
Gradle版本: 8.11.1
JDK版本: 21

BUILD SUCCESSFUL in 755ms
1 actionable task: 1 executed

Build Analyzer results available
18:05:12: Execution finished 'printVersion'.

可以看到,打印的jdk版本为21,这充分说明了Android Studio在调用Gradle时使用的是Gradle JDK中指定的JDK版本来运行Gradle,它不会使用JAVA_HOME,也不会使用gradle.properties中指定的JDK版本。这是很奇怪的,因为Gradle JDK是在IDE中设置的,无法加入到版本控制,所以同一个项目多人开发时,可能会指定不同版本的Gradle JDK,导致有的人编译正常,有的人编译出问题。

不同Gradle版本和AGP版本对JDK的支持

Android官网中Kotlin版本所需要的AGP、D8和R8版本:https://developer.android.com/build/kotlin-support?hl=zh-cn

Kotlin 版本所需的 AGP 版本所需的 D8 和 R8 版本
1.34.12.1.86
1.47.03.0.76
1.57.03.0.77
1.67.13.1.51
1.77.23.2.47
1.87.44.0.48
1.98.08.0.27
2.08.58.5.10
2.18.68.6.17
2.28.108.10.21

AGP版本对Gradle版本需求的表格:https://developer.android.google.cn/build/releases/gradle-plugin?hl=zh-cn

插件版本所需的最低 Gradle 版本
8.108.11.1
8.98.11.1
8.88.10.2
8.78.9
8.68.7
8.58.7
8.48.6
8.38.4
8.28.2
8.18.0
8.08.0
7.47.5
7.37.4
7.27.3.3
7.17.2
7.07.0
4.2.0+6.7.1
4.1.0+6.5+
4.0.0+6.1.1+
3.6.0 - 3.6.45.6.4+
3.5.0 - 3.5.45.4.1+
3.4.0 - 3.4.35.1.1+
3.3.0 - 3.3.34.10.1+
3.2.0 - 3.2.14.6+
3.1.0+4.4+
3.0.0+4.1+

Android Gradle 插件和 Android Studio 兼容性:https://developer.android.google.cn/build/releases/gradle-plugin?hl=zh-cn#android_gradle_plugin_and_android_studio_compatibility

Android Studio 版本所需的 AGP 版本
Narwhal 功能更新 | 2025.1.24.0-8.12
Narwhal | 2025.1.13.2-8.11
Meerkat 功能更新 | 2024.3.23.2-8.10
Meerkat | 2024.3.13.2-8.9
Ladybug 功能更新 | 2024.2.23.2-8.8
Ladybug | 2024.2.13.2-8.7
Koala 功能更新 | 2024.1.23.2-8.6
Koala | 2024.1.13.2-8.5
Jellyfish | 2023.3.13.2-8.4
Iguana | 2023.2.13.2-8.3
Hedgehog | 2023.1.13.2-8.2
Giraffe | 2022.3.13.2-8.1
Flamingo | 2022.2.13.2-8.0

对于AGP对最小JAVA版本的支持,官方没有给出表格,但是可以从每个APG版本的链接中去查看:https://developer.android.google.cn/build/releases/past-releases?hl=zh-cn,比如对于AGP 8.9.0版本,官网的兼容性如下:
在这里插入图片描述
如上图可看到AGP 8.9.0需求的最低Gradle版本、最低JDK版本、最低SDK Build Tools版本、最低NDK版本,以及对应的默认版本。

Gradle官网中列出了Java版本所支持运行的最低Gradle版本的列表:https://docs.gradle.org/current/userguide/compatibility.html,同时还有kotlint和Gradle版本的支持列表。

下面把Gradle官网中的关于Java和Gradle,以及Kotlin和Gradle的需求列表复制过来:

Java 版本支持工具链需求的最低 Gradle版本
8不适用2.0
9不适用4.3
10不适用4.7
11不适用5.0
12不适用5.4
13不适用6.0
14不适用6.3
156.76.7
167.07.0
177.37.3
187.57.5
197.67.6
208.18.3
218.48.5
228.78.8
238.108.10
248.148.14
25不适用不适用

这里的Java版本与Gradle版本中,Gradle是最低版本要求,比如JAVA21与Gradle 8.5对应,则如果你要用Java21来运行Gradle,则最少需要Gradle 8.5或更高的版本,如果比8.5低的则Java21运行不了。

https://docs.gradle.org/current/userguide/toolchains.html,这里是对java工具链的解释,Java 工具链是一组用于构建和运行 Java 项目的工具,简单理解java工具链其实就是java、javac、javadoc等工具的一个总称,但是文档中关于工具链又有好多概念,烦死个人,学不完啊,太难了。对于工具链我的理解是可以配置编译Gradle项目的jdk版本,比如:

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17)) // 指定Java 17专用工具链
    }
}

这个设置就是说用JDK17来编译项目,Gradle会先从本地查找JDK17,如果找不到就会自动下载一个。

设置与不设置工具链有什么区别?运行Gradle是需要JDK支持的,如果不设置工具链,则编译项目时使用的JDK将和运行Gradle的JDK版本一样,如果设置了工具链,则运行Gradle的JDK版本可以和编译项目的JDK版本不一样。

问了一下DeepSeek,解释说:

  • 工具链最直接的用途就是​​解耦编译/运行环境的 JDK 版本​​。

  • 未支持工具链时的行为:当 Gradle 不支持工具链时(如 Java 8-14),编译(javac)和运行(java)强制使用​​同一个 JDK​​(即运行 Gradle 的 JVM)。

  • 工具链管理的远不止 JDK 版本!它是一套​​完整的开发工具集​​,包含以下分层控制:

    控制维度工具链实现能力单纯切换 JDK 的局限性
    编译器版本精准选择 javac 版本(如 Java 11 的编译器)❌ 只能整体切换 JDK
    运行时环境测试/运行时用不同 JVM(如 IBM J9、OpenJ9)❌ 绑定到系统 JDK
    工具集扩展集成代码检查、文档生成等独立工具❌ 仅含基础编译运行功能
    跨平台管理自动下载缺失的 JDK(指定厂商/版本)❌ 需手动安装配置

    工具链 = JDK + 编译器 + 调试器 + 分析工具 + 跨平台管理​

我问了DeepSeek一个具体应用:项目需兼容 Java 8,但开发者用 Java 17,比如我用Android Studio开发Android项目,写代码时我想使用Java 17,但是编译后我希望可以兼容Java8,如何实现?DeepSeek的回答如下:

在Android开发中实现“使用Java 17编写代码,但编译后兼容Java 8”的需求,本质是通过​​构建工具的分层控制​​解决JDK版本冲突。以下是完整实现方案,结合Gradle工具链和兼容性配置:

层级开发者环境(写代码)构建环境(编译)目标环境(运行)
JDK版本Java 17Java 17Java 8
关键技术Android StudioGradle工具链字节码降级
控制目标使用新语法生成兼容字节码旧设备可运行

✅ ​​关键点​​:
工具链控制编译阶段JDK(Java 17),targetCompatibility控制输出字节码版本(Java 8)。

具体配置:

android {
    compileOptions {
        // 指定源码使用Java 17语法
        sourceCompatibility JavaVersion.VERSION_17
        // 输出兼容Java 8的字节码
        targetCompatibility JavaVersion.VERSION_1_8
    }

    // 配置工具链使用JDK 17编译
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

检查字节码版本:

编译后执行命令验证classes.dex兼容性:

dexdump -f app/build/intermediates/dex/debug/classes.dex | grep 'min-sdk-version'

输出应为min-sdk-version: 0x00000018(即API 24,对应Java 7+,兼容Java 8)

脱糖

一、Java 版本自动脱糖特性与 AGP 版本对应表

Java 版本支持的自动脱糖特性所需最低 AGP 版本依赖库特性说明
Java 8Lambda 表达式、方法引用、默认接口方法、Stream APIOptional4.0.0desugar_jdk_libs:1.1.9+需显式开启 coreLibraryDesugaringEnabled=true
Java 11var 局部变量推断、HTTP Client API、java.nio.file 子集7.4.0desugar_jdk_libs:2.0.0+语言特性脱糖由 D8/R8 自动处理
Java 17Sealed Classes(密封类)、Switch 模式匹配、Record 类8.0.0需 JDK 17 编译环境仅语法脱糖,部分 API(如 StackWalker)需手动适配
Java 21虚拟线程(正式版)、分代 ZGC 优化、Vector API8.7.0+需 Gradle 8.5+ 和 JDK 21虚拟线程需 Android 14+(API 34)原生支持

说明:在AGP 4.0.0版本的时候脱糖要显示开启coreLibraryDesugaringEnabled=true,但到了APG 7.4.0的时候则不用了,这不仅是针对Java 11还针对Java 8。

二、不支持自动脱糖的 Java 特性列表

特性类型具体特性示例限制原因
JVM 底层特性Java 模块化系统(JPMS)需深度集成 JVM,无法通过字节码转换实现
新 APIjava.lang.StackWalker
java.util.stream.Collectors.teeing
依赖 JVM 内部实现,脱糖库无法模拟
编译时特性Record 模式匹配(if (obj instanceof Point(int x, int y))需 AGP 8.0+ minSdkVersion >= 34
并发模型虚拟线程(Virtual Threads)需 Android 14+(API 34)原生支持,低版本设备无法脱糖
### Gradle 构建工具 Java 版本兼容性 Gradle 支持多种不同版本Java 开发环境,确保了广泛的兼容性。对于不同的 Gradle 版本而言,支持的具体 Java 版本范围有所不同: - **最低要求**:自 Gradle 6.0 起,至少需要 JDK 8 或更高版本才能运行 Gradle[^3]。 - **推荐配置**:为了获得最佳体验和支持最新的语言特性和库,建议使用最新发布的 LTS (Long Term Support) 版本JDK。 当涉及到特定项目的构建时,可以通过 `gradle.properties` 文件中的属性来指定所需的 Java 版本。例如,在此文件内添加如下设置可强制项目使用特定版本Java 编译器: ```properties org.gradle.java.home=/path/to/java/home ``` 此外,还可以通过命令行参数传递给 Gradle 来临时更改使用的 Java 安装路径: ```bash GRADLE_OPTS="-Dorg.gradle.java.home=/path/to/java" ./gradlew build ``` 这种灵活性让开发者能够在不改变全局环境的情况下测试不同版本下的行为差异。 ### 配置指南 要为一个新创建或现有项目设定合适的 Java 版本约束,可以在项目的根目录下的 `build.gradle` 文件里加入相应的指令集。下面是一个简单的例子展示如何声明目标源码级别以及字节码级别的兼容性选项: ```groovy apply plugin: 'java' sourceCompatibility = '11' targetCompatibility = '11' ``` 上述代码片段表明该工程将采用 Java 11 的语法特性进行编译,并生成适用于 JVM 11 执行的标准类文件格式。如果希望进一步控制所依赖的第三方库也需要遵循相同的 Java 版本,则可以考虑引入额外的插件如 `java-library` 插件并调整相应部分的配置项。 另外值得注意的是,随着每次发布新的主要版本更新,官方文档都会详细记录哪些旧版功能被弃用或是移除;因此保持关注官方公告有助于及时了解可能影响到当前工作的变动情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

android_cai_niao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值