How to use java toolchain with plugin?
austinarbor opened this issue · comments
It looks like some code was added to help use a configured java toolchain (https://github.com/melix/jmh-gradle-plugin/blob/master/src/main/java/me/champeau/jmh/WithJavaToolchain.java), but I can't seem to get it to work.
When I try
tasks.withType(me.champeau.jmh.JmhBytecodeGeneratorTask).configureEach {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
}
}
I get the error > error: invalid source release: 17
When I try
tasks.withType(me.champeau.jmh.JMHTask).configureEach {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
}
}
I get the error
has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
If I already have jdk17 in the shell, everything works fine. Can you let me know what I am doing wrong to use the toolchain?
Thanks
I also just tried
jmh {
javaLauncher.set(
javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
}
)
}
But that gave me the same error as the 2nd attempt above
@austinarbor You may need to set this on the compile tasks as well.
Indeed the toolchain configures the default compileJava
task but not the one that is created by the JMH Gradle plugin
This is what what I use (ignore the panama flags, options), to run Gradle with JDK 17 but run benchmarks of JDK 18 code.
Notice this code is snippet is kotlin script.
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(18))
}
}
val launcher = javaToolchains.launcherFor(java.toolchain).get()
jmh {
jvm.set(launcher.executablePath.asFile.absolutePath)
}
tasks {
withType<JavaCompile>().configureEach {
options.compilerArgs = listOf(
"--add-modules", "jdk.incubator.foreign"
)
options.release.set(18)
javaCompiler.set(project.javaToolchains.compilerFor(java.toolchain))
}
withType<JavaExec>().configureEach {
environment("JAVA_LIBRARY_PATH", ".:${project.projectDir}/jni")
jvmArgs("--enable-native-access=ALL-UNNAMED",
"--add-modules", "jdk.incubator.foreign")
javaLauncher.set(project.javaToolchains.launcherFor(java.toolchain))
}
withType<JmhBytecodeGeneratorTask>().configureEach {
javaLauncher.set(project.javaToolchains.launcherFor(java.toolchain))
}
}
@bric3 thanks for the suggestion - unfortunately that resulted in the same error for me
java.lang.UnsupportedClassVersionError: ... has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0
What java version are you using when you run the commands? If I do everything with 17 set in my current shell it works fine - but once I switch to Java 8 to make sure the toolchain is working, it produces an error
Do you have a reproducer?
@bric3 try running ./gradlew jmh
on https://github.com/austinarbor/jmh-toolchain-issue with anything lower than 17
Ah of course, I forgot to mention to set the jvm
parameter in the jmh
configuration, updating my comment above.
So basically in your reproducer you should add. I've kept the repetition of the javaToolchains.launcherFor
but you might want to refactor this in a single variable.
diff --git i/build.gradle w/build.gradle
--- i/build.gradle
+++ w/build.gradle
@@ -16,6 +16,25 @@ java {
}
}
+jmh {
+ jvm = javaToolchains.launcherFor({
+ languageVersion = JavaLanguageVersion.of(17)
+ }).get().executablePath.asFile.absolutePath
+}
+
+tasks.withType(JavaCompile).configureEach {
+ javaCompiler = project.javaToolchains.compilerFor {
+ languageVersion = JavaLanguageVersion.of(17)
+ }
+}
+
+
+tasks.withType(JavaExec).configureEach {
+ javaLauncher = javaToolchains.launcherFor {
+ languageVersion = JavaLanguageVersion.of(17)
+ }
+}
+
tasks.withType(me.champeau.jmh.JmhBytecodeGeneratorTask).configureEach {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
@bric3 thanks, that seems to get it working. I refactored into the below. Unfortunately it's still quite verbose, I wish there was an easier way. Do you know why the JavaCompile
configuration is required? Based on gradle docs I thought that was handled automatically by the toolchain
- Setup all compile, test and javadoc tasks to use the defined toolchain which may be different than the one Gradle itself uses
def javaVersion = JavaLanguageVersion.of(17)
def compiler = javaToolchains.compilerFor {
languageVersion = javaVersion
}
def launcher = javaToolchains.launcherFor {
languageVersion = javaVersion
}
java {
toolchain {
languageVersion = javaVersion
}
}
jmh {
jvm = launcher.get().executablePath.asFile.absolutePath
}
tasks.withType(JavaCompile).configureEach {
javaCompiler = compiler
}
tasks.withType(me.champeau.jmh.JmhBytecodeGeneratorTask).configureEach {
javaLauncher = launcher
}
Do you know why the
JavaCompile
configuration is required
That's because the toolchain support only configures the default one from the java plugin. I think this a prudent default form the gradle team.
Ah yea this makes total sense. For some reason my brain wasn't grokking that the JMH task was using its own compilation task. Thanks for all the help
I ran into the same issue just now and quickly prototyped #228 to make the interaction with toolchains (in my opinion) more intuitive.
Fixed by #228