介绍
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.copy
、ant.jar
),Gradle
会通过其内置的Ant
引擎执行这些操作。 - 对从
Ant
或Maven
迁移到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 的区别
-
Launcher JVM(启动器 JVM)
- 作用:当执行
gradlew
命令时,系统会启动一个临时JVM进程(即Launcher JVM),该进程仅负责:- 解析命令行参数 (如-v、build等);
- 检查是否存在兼容且空闲的守护进程,若不存在则创建一个守护进程,存在则复用这个守护进程,将构建任务委托给守护进程,自身立即退出。
- 生命周期:
- 仅在执行 Gradle 命令时短暂存在(如执行
./gradlew -v
)。 - 完成任务后立即退出,不参与实际构建过程。
- 仅在执行 Gradle 命令时短暂存在(如执行
- 配置依赖:使用当前终端环境变量
JAVA_HOME
,如果没有JAVA_HOME
则使用系统默认JDK
。
- 作用:当执行
-
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+已默认启用)
- 优先读取项目配置(
-
为什么要有这两种不同的进程
Gradle
的运行依赖于Java
运行环境,这肯定是依赖于系统的JAVA_HOME
或默认安装的JDK
,假如你安装了多个JDK
,Gradle
无法知道你要用哪一个JDK
,所以只能用JAVA_HOME
指定的,如果没有设置JAVA_HOME
那就只能用PATH
环境变量中能找到的那个(即默认JDK
)。- 当
Gradle
运行起来后,它才能去读取gradle.properties
文件中的org.gradle.java.home
属性,然后才能用该属性指定的JDK
版本再启动一个Gradle Daemon
。
-
总结
- 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 JVM
是jdk17
,而我们自定义的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.3 | 4.1 | 2.1.86 |
1.4 | 7.0 | 3.0.76 |
1.5 | 7.0 | 3.0.77 |
1.6 | 7.1 | 3.1.51 |
1.7 | 7.2 | 3.2.47 |
1.8 | 7.4 | 4.0.48 |
1.9 | 8.0 | 8.0.27 |
2.0 | 8.5 | 8.5.10 |
2.1 | 8.6 | 8.6.17 |
2.2 | 8.10 | 8.10.21 |
AGP版本对Gradle版本需求的表格:https://developer.android.google.cn/build/releases/gradle-plugin?hl=zh-cn
插件版本 | 所需的最低 Gradle 版本 |
---|---|
8.10 | 8.11.1 |
8.9 | 8.11.1 |
8.8 | 8.10.2 |
8.7 | 8.9 |
8.6 | 8.7 |
8.5 | 8.7 |
8.4 | 8.6 |
8.3 | 8.4 |
8.2 | 8.2 |
8.1 | 8.0 |
8.0 | 8.0 |
7.4 | 7.5 |
7.3 | 7.4 |
7.2 | 7.3.3 |
7.1 | 7.2 |
7.0 | 7.0 |
4.2.0+ | 6.7.1 |
4.1.0+ | 6.5+ |
4.0.0+ | 6.1.1+ |
3.6.0 - 3.6.4 | 5.6.4+ |
3.5.0 - 3.5.4 | 5.4.1+ |
3.4.0 - 3.4.3 | 5.1.1+ |
3.3.0 - 3.3.3 | 4.10.1+ |
3.2.0 - 3.2.1 | 4.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.2 | 4.0-8.12 |
Narwhal | 2025.1.1 | 3.2-8.11 |
Meerkat 功能更新 | 2024.3.2 | 3.2-8.10 |
Meerkat | 2024.3.1 | 3.2-8.9 |
Ladybug 功能更新 | 2024.2.2 | 3.2-8.8 |
Ladybug | 2024.2.1 | 3.2-8.7 |
Koala 功能更新 | 2024.1.2 | 3.2-8.6 |
Koala | 2024.1.1 | 3.2-8.5 |
Jellyfish | 2023.3.1 | 3.2-8.4 |
Iguana | 2023.2.1 | 3.2-8.3 |
Hedgehog | 2023.1.1 | 3.2-8.2 |
Giraffe | 2022.3.1 | 3.2-8.1 |
Flamingo | 2022.2.1 | 3.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 |
15 | 6.7 | 6.7 |
16 | 7.0 | 7.0 |
17 | 7.3 | 7.3 |
18 | 7.5 | 7.5 |
19 | 7.6 | 7.6 |
20 | 8.1 | 8.3 |
21 | 8.4 | 8.5 |
22 | 8.7 | 8.8 |
23 | 8.10 | 8.10 |
24 | 8.14 | 8.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 17 | Java 17 | Java 8 |
关键技术 | Android Studio | Gradle工具链 | 字节码降级 |
控制目标 | 使用新语法 | 生成兼容字节码 | 旧设备可运行 |
✅ 关键点:
工具链控制编译阶段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 8 | Lambda 表达式、方法引用、默认接口方法、Stream API 、Optional 类 | 4.0.0 | desugar_jdk_libs:1.1.9+ | 需显式开启 coreLibraryDesugaringEnabled=true |
Java 11 | var 局部变量推断、HTTP Client API、java.nio.file 子集 | 7.4.0 | desugar_jdk_libs:2.0.0+ | 语言特性脱糖由 D8/R8 自动处理 |
Java 17 | Sealed Classes(密封类)、Switch 模式匹配、Record 类 | 8.0.0 | 需 JDK 17 编译环境 | 仅语法脱糖,部分 API(如 StackWalker )需手动适配 |
Java 21 | 虚拟线程(正式版)、分代 ZGC 优化、Vector API | 8.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,无法通过字节码转换实现 |
新 API | java.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)原生支持,低版本设备无法脱糖 |