Sebastian Schuberth
03/12/2024, 5:49 PMjava {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
in my project, and I have a JDK 17 installed (that can compile to Java 11 bytecode), will Gradle use it, or provision exactly JDK version 11?Chris Lee
03/12/2024, 5:56 PMSebastian Schuberth
03/12/2024, 5:58 PMtargetCompatibility
directly than using the toolchains mechanism?Chris Lee
03/12/2024, 5:59 PMSebastian Schuberth
03/12/2024, 6:01 PMChris Lee
03/12/2024, 6:02 PMSebastian Schuberth
03/12/2024, 6:28 PMChris Lee
03/12/2024, 6:29 PMGradle also doesn’t redownload a dependency if it’s already present in local Maven (!) repository.It had to do the one-time hit to download it initially, same as with toolchains.
Caleb Cushing
03/12/2024, 10:07 PMtasks.compileJava {
options.release = 11
}
Vampire
03/13/2024, 8:45 AMIt had to do the one-time hit to download it initially, same as with toolchains.Indeed it does not @Chris Lee, Gradle checks for a file with the right checksum in maven local even for remote dependencies and if no maven local is configured otherwise to save the download time if Maven happened to have dowloaded the artifact already in the past.
I really wonder why toolchains behave like this.I would really wonder if they did not, because that is what you asked it to do. You ask "use a Java 11 toolchain", not "use a toolchain able to produce Java 11 bytecode". For that you are after https://github.com/gradle/gradle/issues/16256 with which you could do it.
Gradle puts so much effort into build performanceBut it luckily puts more effort into build correctness, so that we do not end up like Maven users which should use
clean
in practically every invocation to get a result as correct as possible.
build correctness > build performance imho.
I guess it's still better to setI would say no, never. Usingdirectly than using the toolchains mechanism?targetCompatibility
*Compatibility
is dangerous.
If you for example have a Java 21 toolchain, and have compatibility set to 11, and use in your code ByteBuffer.flip
, then your result will be code that is compatible with Java 11 as far as the bytcode version concerns, but will fail at runtime with "method not found" if you are using Java 11 or Java 12.
If you really want to avoid toolchains (I would not), at least use release
instead of *Compatibility
which makes sure those API changes do not bite you.
But I personally would not so much be concerned about the performance. On CI you can easily assure that the toolchain is already available and on non-CI, it is one download that is then reused by everyone needing the same toolchain.
You can also work-around it a bit by not setting the toolchain at all if the toolchain running Gradle is sufficient like in the work-around in the issue linked above, but makes sure to then also use release
.Sebastian Schuberth
03/13/2024, 9:19 AMthen your result will be code that is compatible with Java 11 as far as the bytcode version concerns, but will fail at runtime with "method not found" if you are using Java 11 or Java 12.Good point that used methods might be missing in an older runtime. I haven't though about that case.
Vampire
03/13/2024, 9:36 AMVampire
03/13/2024, 9:36 AMflip
was inherited from Buffer
and had Buffer
as return type.
In Java 13 it got overridden in ByteBuffer
and there returns ByteBuffer
.
And that breaks your neck if you compile against the wrong API.Vampire
03/13/2024, 9:37 AMSebastian Schuberth
03/13/2024, 9:38 AMAnze Sodja
03/13/2024, 9:44 AMjavax.
packages that were removed in Java11. So one could set toolchains to Java 8 and if Gradle would happily use any Java >= 8, then the build could work on a machine with Java8, but not on one with Java11.Vampire
03/13/2024, 10:29 AMrelease
set to 8, you would get the exact same result.
If Gradle would use Java 11 without release
it would not build as then the Java 11 API would be compiled against which misses the method and would fail compilation.Anze Sodja
03/13/2024, 10:45 AMrelease
set to 8, you would get the exact same result.
So if Gradle would work like that when Java8 is requested, then with Java11 I believe you would get compilation errors that javax
package doesn't exist (unless you add a dependency manually) if you use some javax
in your code.
While with Java8 compilation would pass.
And if you remove javax
package suddenly the project would compile also with Java11.Caleb Cushing
03/13/2024, 10:49 AMVampire
03/13/2024, 11:30 AMI believe you would get compilation errors thatI don't think so. That's exactly whatpackage doesn't existjavax
release
is for, to compile against API of older versions.
And that is then equal to compiling with Java 8 toolchain
As I said, with Java 11 but without release
you would get the compile error you described.
But initially you said with a Java 11 toolchain you would get code that runs on Java 8 - 10 but not with 11+, while with Java 8 you would not have that problem and that is what I don't understand what you meant.Vampire
03/13/2024, 11:31 AMVampire
03/13/2024, 11:32 AMrelease
is set to 8
which it at least currently is, if you use the toolchains feature.Vampire
03/13/2024, 11:32 AMrelease
flag.Sebastian Schuberth
03/13/2024, 4:04 PMVampire
03/13/2024, 5:04 PMjavaToolchains.compilerFor(java.toolchain).map { it.metadata.jvmVersion }
javaToolchains.compilerFor(java.toolchain).map { it.metadata.javaRuntimeVersion }
Sebastian Schuberth
03/13/2024, 6:15 PMlauncherFor
.Vampire
03/13/2024, 6:16 PMlauncherFor
, all the tools should have the metadata fieldVampire
03/13/2024, 6:17 PM