基础知识科普
Android工程的Gradle JDK,以及代码里面配置的jvmTarget有什么区别?
这是两个完全不同的概念:
Gradle JDK:指的是用于运行Gradle构建系统的Java Development Kit版本。Gradle是Android项目的构建工具,它负责处理项目的编译、打包、依赖管理等任务。Gradle JDK的选择决定了在构建过程中使用的Java版本。
jvmTarget:是java或者Kotlin代码中配置的一个属性。用于指定生成的java或者Kotlin字节码的目标JVM版本。Kotlin编译器将根据该属性生成符合目标JVM版本的字节码。这个属性与Gradle JDK的版本设置是不同的。如果该属性没有设置,会使用跟Gradle jdk相同的版本。
AGP升级的过程,主要是Gradle JDK的版本的修改,所以为了尽量不影响代码功能,我们应该为java和kotlin代码指定具体的jvmTarget,这个Gradle JDK的升级,只需要适配编译脚本的jdk兼容性,而不需要考虑代码的jdk兼容性。
问题及解决方案
AGP升级过程中,经常遇到的问题:
AGP升级与Gradle,JDK版本的对应关系:
AGP | 最低 Gradle | 最低JDK | SDK Build Tools | 建议Kotlin插件版本 |
8.1 | 8.1 | Jdk 17 | 30.0.3 | 1.8.10 |
8.0 | 8.0 | Jdk 17 | 30.0.3 | 1.7.10 |
7.4 | 7.5 | Jdk 11 | 30.0.3 | 1.6.21 |
7.3 | 7.4 | Jdk 11 | 30.0.3 | 1.5.21 |
7.2 | 7.3.3 | Jdk 11 | 30.0.3 | 1.5.0 |
7.1 | 7.2 | Jdk 11 | 30.0.3 | 1.5.0 |
7.0 | 7.0.2 | Jdk 11 | 30.0.2 | 1.5.0 |
4.2.0 | 6.7.1 | Jdk 8 | 29.0.2 | 1.4.x |
4.1.0 | 6.5 | Jdk 8 | 29.0.2 | 1.3.72 |
4.0.1 | 6.1.1 | Jdk 8 | 29.0.2 | 1.3.61 |
3.4.x | 5.1.1 | Jdk 8 | 28.0.3 | 1.3.11 |
3.2.1 | 4.6 | Jdk 8 | 28.0.3 | 1.3.x |
3.1.0 | 4.4 | Jdk 8 | 27.0.3 | 1.2.x |
3.0.1 | 4.1 | Jdk 8 | 26.0.2 | 1.1.x |
大家从上图可以看出,每次Android编译系统AGP的升级,尤其是大版本的变动,都会导致Jdk的升级,而jdk升级,很容易导致编译出错。
编译过程中具体的错误堆栈如下:
14:10:12 * What went wrong: 14:10:12 Execution failed for task ':xxWidget:kaptGenerateStubsReleaseKotlin'. 14:10:12 > 'compileReleaseJavaWithJavac' task (current target is 1.8) and 'kaptGenerateStubsReleaseKotlin' task (current target is 17) jvm target compatibility should be set to the same Java version. 14:10:12 Consider using JVM toolchain: Configure a Gradle project | Kotlin Documentation 14:10:12 14:10:12 14:10:12 * Try: 14:10:12 > Run with --info or --debug option to get more log output. 14:10:12 > Run with --scan to get full insights. 14:10:12 14:10:12 * Exception is: 14:10:12 org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':QYWidget:kaptGenerateStubsReleaseKotlin'.
从上面的错误类型可以看到,编译java代码和kotlin代码不一致导致了该问题,那我们该怎么修改呢?有两个修改方向,一个是java编译升级到17,与kotlin保持一致。另一个是kotlin降级到1.8,与java保持一致。
关于指定具体工程的java和kotlin编译jdk版本,具体方法如下:
情况一:针对基于android的插件,在对应的build.grade配置文件中,添加如下的配置:
android { compileOptions { encoding = 'UTF-8' // Sets Java compatibility to Java 8 sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } try { kotlinOptions { jvmTarget = "1.8" } } catch(Exception ignored) { //ignore } } tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { kotlinOptions.jvmTarget = "1.8" }
从上图可以看出,compileOptions里面的配置解决的是java代码编译的jdk版本,而kotlinOptions里面的配置解决的是kotlin代码的jdk版本,而kaptGenerateStubsReleaseKotlin的编译版本通过下马tasks.withType的方式来配置。
情况二:针对java库插件,对应的配置如下:
plugins { id 'java-library' id 'kotlin' } java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } kotlin { jvmToolchain(8) }
当出现java和kotlin编译jdk不兼容的时候,官方的建议是:consider to use java toolchain.