gradle中的刀具链参数

gab6jxml  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(213)

我的问题是关于gradle中的toolchain.languageVersion.set(JavaLanguageVersion.of(17))参数。
我有一个用Java 8编写的Java项目,并使用Gradle 6.7构建:

cat build.gradle

plugins {
    id 'java'
    id 'application'
    id 'com.palantir.docker' version '0.25.0'
}

我已经通过在build.gradle中添加toolchain.languageVersion.set(JavaLanguageVersion.of(17))参数将java 8升级到java 17。这个更新迫使我将Gradle从6.7升级到8.1.1,同时更新了其中一个插件的版本。把所有这些放在一起,build.gradle文件看起来像这样:

plugins {
    id 'java'
    id 'application'
    id 'com.palantir.docker' version '0.35.0' //update version from 0.25.0 to 0.35.0
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

toolchain参数告诉gradle使用java 17运行gradle-tasks,以及设置源兼容性和目标兼容性参数。
当我在本地机器上安装了java 17时,构建是成功的,但是如果我使用java 8,那么我会得到一个错误:“java.lang.UnsupportedClassVersionError:com/palantir/gradle/docker/DockerComponent已由较新版本的Java运行时(类文件版本55.0)编译,此版本的Java运行时仅识别最高达52.0的类文件版本。
这是错误的行为,因为toolchain配置应该解决这个问题。
我该怎么解决这个问题?
P.S.有同样的问题gradle网站,但没有答案:https://discuss.gradle.org/t/specifying-gradle-version-and-java-toolchain-version-isnt-enough/41111
我还读过一篇关于toolchain参数的文章:https://stefma.medium.com/sourcecompatibility-targetcompatibility-and-jvm-toolchains-in-gradle-explained-d2c17c8cff7c
这里有三个有趣的段落:
通过此设置,您使用哪个JDK版本来运行Gradle(任务)“不再重要”。您甚至可以在版本8中使用本地安装的JDK。Gradle会检测到它应该在版本17中使用JDK来构建(编译、测试等),所以它会为你下载并存储在~/.gradle/jdks中以供以后重用。
细心的读者可能会注意到,我在上面的章节中放置的双引号不再重要。这是故意的,因为所有这些的问题是,您在本地(以及在持续集成服务器机器上)安装了哪个JDK来运行Gradle(任务)确实很重要。
正如本博客开头提到的,AGP 8.0需要Java 17。这就是它的含义。这并不意味着源代码或目标(字节码)需要在版本17中编写,这意味着AGP本身需要Java 17,因为它在版本17中是用JDK编译的,或者至少targetCompatibility设置为版本17。
但我不理解他们因为他们互相联系

nx7onnlm

nx7onnlm1#

java. lang. UnsupportedClassVersionError:com/palantir/gradle/docker/DockerComponent已由Java Runtime的最新版本(类文件版本55.0)编译,此版本的Java Runtime仅识别最高版本52.0以下的类文件
toolchain参数告诉gradle使用java 17运行gradle-tasks,以及设置源兼容性和目标兼容性参数。
在构建Java项目时,有多个JVM示例在运行。
第一个JVM进程是Gradle本身。Gradle是一个Java程序,因此需要一个JVM示例来执行。这是您在计算机上全局安装的任何版本。
接下来,对于您自己的Java项目的任何编译、运行或测试,Gradle将为其中的每一个开发一个新的JVM进程。这个JVM进程不需要与Gradle进程本身运行的JVM版本相同。这就是工具链来的地方。它只适用于Gradle需要运行时产生的子进程,例如编译或测试。Gradle将通过工具链功能下载JDK,仅用于那些用于处理您自己的Java代码的子JVM进程。
Gradle不会下载自己的JDK来执行自己,因为它需要预先安装的JDK来解析自己的文件并下载工具链JDK。
你得到的错误是因为你需要至少有JDK 11才能使用com.palantir.docker插件的特定版本(https://docs.oracle.com/javase/specs/jvms/se20/html/jvms-4.html#jvms-4.1-200-B.2),但是假设你的系统上预装了JDK 11。以下是事件的顺序:
1.执行Gradle命令:gradle compileJava

  1. JVM 11进程在运行Gradle的机器上运行
  2. Gradle解析自己的文件,下载插件JAR,并执行插件
  3. Gradle查看工具链设置并检查系统上是否已经安装了JDK 17版本
    1.如果没有,Gradle将下载JDK 17版本
  4. Gradle(JVM 11进程)从它下载的JDK 17中生成子Java编译进程(通过compileJava任务
    1.您的代码是用Java 17编译器编译的
  5. Java 17编译器退出
  6. compileJava任务(在JVM11进程中)完成
    1.主Gradle程序(在JVM11进程中)完成
  7. JVM 11进程退出
    1.命令提示符将返回给您
    因此,总而言之,工具链与Gradle主进程无关。Gradle将从工具链中下载的JDK作为子进程执行。

相关问题