Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Java 16 #13481

Closed
sbrannen opened this issue Jun 17, 2020 · 30 comments
Closed

Support Java 16 #13481

sbrannen opened this issue Jun 17, 2020 · 30 comments
Assignees
Labels
a:feature A new functionality @core Issue owned by GBT Core
Milestone

Comments

@sbrannen
Copy link

Current attempts to use Gradle 6.5 with openjdk version "16-ea" 2021-03-16 result in a failure along the lines of:

> Task :buildSrc:validatePlugins FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':buildSrc:validatePlugins'.
> There was a failure while executing work items
   > A failure occurred while executing org.gradle.plugin.devel.tasks.internal.ValidateAction
      > Unsupported class file major version 60

Please add support for Java 16.

Note, however, that the above failure is due to lack of support for Java 16 in ASM.

@rdehuyss
Copy link

rdehuyss commented Jul 7, 2020

I would love to evaluate project loom for my library (https://github.com/jobrunr/jobrunr) but since that is only available in jdk 16 and I also use gradle this is difficult now.

@eskatos
Copy link
Member

eskatos commented Jul 7, 2020

@rdehuyss you can use different JVMs for running Gradle and compiling/running tests, see https://docs.gradle.org/current/userguide/building_java_projects.html#sec:java_cross_compilation

@rdehuyss
Copy link

rdehuyss commented Jul 7, 2020

@eskatos , thanks! I did not know that...

@lppedd
Copy link

lppedd commented Aug 4, 2020

@rdehuyss were you able to test Loom using Gradle or did you switch to Maven?
Sorry for this small OT.

@rdehuyss
Copy link

rdehuyss commented Aug 5, 2020

I put it on my backlog for the moment...

@lppedd
Copy link

lppedd commented Aug 5, 2020

@rdehuyss I tested it. Instructions by @eskatos works perfectly. It's a matter of minutes.

@rdehuyss
Copy link

@lppedd Thx for your feedback. It indeed wasn't that much work. I'm testing JobRunr now with Project Loom and all seems ok. I still need to do further performance testing.

@eskatos I also have automated tests (it's a test where JobRunr is tested against 12 different JVM's - see also https://www.jobrunr.io/blog/testing-jobrunr-against-12-different-jvms/) where the approach mentioned above is difficult. Since ASM 9 is now available in beta with support for JDK 16, what are the plans for gradle?

@mikehearn
Copy link

mikehearn commented Oct 11, 2020

This problem really needs to be fixed in a more general way than just bumping ASM versions and doing a new Gradle release.

The problem is that Gradle (sometimes via Groovy) really wants to analyse bytecode in various ways at various points, and pukes when it can't. This is very hard to fix directly because bytecode is not forwards compatible, so you can't analyse versions from the future.

There is therefore only one robust solution: javac must be told to emit old bytecode versions. This it can easily do via the -target and -source flags. Currently it doesn't work because Gradle is still living in a world where new Java versions were rare events, so it just blithely assumes that whatever Java version is running it is the version it should pass to -target/-source. It passes -target 16 -source 16 to javac as part of compiling some Java/Groovy together, the Groovy compiler tries to read the bytecode and can't, then the error gets partly swallowed and it's all a big mess.

This behaviour makes no sense. If Gradle must analyse bytecode then it has only one option it it wants to be compatible with the latest JVMs: it has to cap the target release of any non-user controlled javac invocations at whatever version of Java was the latest supported version at the time of release. This would allow it to be run with the JVM versions "from the future" and still be able to build projects.

That would stem the bleeding, but of course what people want is to be able to use new Java features with old Gradles. They could do so as long as the new feature didn't require new bytecode features (i.e. new APIs but usually not new language features). To support all new Java features with old Gradles implies one of two things:

  1. Gradle must be able to optionally sacrifice its features that rely on reading bytecode (some stuff related to incremental builds, I think?)
  2. Old Gradles must be able to upgrade themselves on the fly to new versions of ASM, because ASM is forwards compatible. This includes ASMs that are lurking, shaded inside Groovy or other dependencies.

The latter approach is definitely the most work, but it would kill the problem once and for all.

At any rate, I hope the Gradle team read this message and think about how to avoid this problem cropping up every six months. As Gradle is not always backwards compatible, the current approach is basically increasing the cost of Java upgrades for Gradle users - now a Java upgrade costs $JAVA_BACKCOMPAT_BREAKS + $GRADLE_BACKCOMPAT_BREAKS. Although I'm sure the Gradle team would love it if everyone upgraded Gradle immediately on upgrade, the world is full of old projects that are parked and no longer receiving significant work. Yet users wish to have a single JDK and still build and work on those old codebases, without upgrading that project's Gradle build. So this feature would help a lot of people over the coming years.

@hugmanrique
Copy link

hugmanrique commented Dec 25, 2020

@eskatos mind elaborating what you set as options.release? I've tried running Gradle with JDK 15, and setting options.release to 15, which obviously fails because it cannot find the new classes. Next, I tried using the EA build by passing -Dorg.gradle.java.home=/home/hugo/panama-b385-jdk-16 to gradlew (keeping options.release = 15). That fails with the Unsupported class file major version 60 error seen above. Finally, I tried setting

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of('16-panama+3-385')
    }
}

which causes an error because #of expects an integer value (the AdoptOpenJDK accepts this version value though, see https://api.adoptopenjdk.net/v3/version/16-panama%2B3-385). The docs also say Gradle doesn't support EA versions. I'm running Gradle v6.7.1, and I cannot find any relevant changes in the RCs that would fix this.

@iotamudelta
Copy link

@hugmanrique what works for me is the following:

gradle.properties:

org.gradle.java.installations.fromEnv=JDK16

build.gradle:

java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(16)
  }
}

You may need to add JVM args to compileJava and test groups, e.g., I have:

compileJava {
  options.warnings = true
  options.deprecation = true
  options.debug = true
  options.compilerArgs += ["--add-modules=jdk.incubator.foreign"]
  options.incremental = false
}
test {
  useJUnitPlatform()
  jvmArgs '--add-modules=jdk.incubator.foreign'
}

build with:

JDK16=/path/to/your/jdk16/home gradle build

(e.g.: JDK16=~/software/jdk16/jdk-16.jdk/Contents/Home gradle build)

@hugmanrique
Copy link

Thank you! Changing from manually specifying the path with org.gradle.java.installations.paths to org.gradle.java.installations.fromEnv did the trick! 😀

@koalalam
Copy link

koalalam commented Jan 11, 2021

Hello @hugmanrique @eskatos @iotamudelta, re: "Changing from manually specifying the path with org.gradle.java.installations.paths to org.gradle.java.installations.fromEnv did the trick", if task validatePlugins honors the toolchain configuration, should both org.gradle.java.installations.paths and org.gradle.java.installations.fromEnv work as well?

Update1:

Both org.gradle.java.installations.paths and org.gradle.java.installations.fromEnv doesn't work for me (Gradle version: 6.7.1). My use case is that JAVA_HOME is set to Java 8, while toolchain config is set to 11:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }

    withJavadocJar()
    withSourcesJar()
}

I have org.gradle.java.installations.paths referencing a JDK 11 distribution.

When I run the build, the Java project is compiled using the JDK11 as expected, however, the task validatePlugins failed:

Execution failed for task ':validatePlugins'.
> There was a failure while executing work items
   > A failure occurred while executing org.gradle.plugin.devel.tasks.internal.ValidateAction
      > test/plugins/BasePlugin has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0

Did I miss anything here?

@kevinrushforth
Copy link

JDK 16 will be released in just over 1 month. Is there any progress on this issue that the gradle team can share?

@ipkpjersi
Copy link

ipkpjersi commented Feb 13, 2021

Is Java 16 support planned for 6.x or is it in 7.x only? What about Java 17 support? I hope both will come to 6.x, ASM is already capable of handling both Java 16 and Java 17. In fact, there was even a new release tagged for ASM (9.1) with Java 16 and Java 17 support just last week.

@dasKeks28
Copy link

As mentioned before by others, ASM (which causes the error) is already able to handle Java 16.
But it seems we're waiting for Gradle to upgrade to use Groovy 3 which "is a prerequisite for Gradle to be able to run on JDK16."
#15566

@tbroyer
Copy link
Contributor

tbroyer commented Feb 27, 2021

Fwiw, #16193 has been merged, so Groovy 3 is there, and available in 7.0-M2.

@xBlackCat
Copy link

Any updates to the issue? Java 16 will be released in a week.

@ice1000
Copy link

ice1000 commented Mar 16, 2021

I think Java 16 will be released in a day now.

@cocorossello
Copy link

7.0 milestone 3 works fine with jdk16

@rieske
Copy link
Contributor

rieske commented Mar 19, 2021

@LifeIsStrange
The error you are seeing with the preview features enabled is because the code is compiled with --enable-preview (JavaCompile task), but then the tests are executed without the preview flag, thus the JVM that is spawned to execute tests does not recognize the bytecode.

In this particular case, you must also set the preview flag on any test tasks that will execute the code compiled with preview features enabled:

tasks.withType<Test>().configureEach {
    jvmArgs("--enable-preview")
}

Note, that the same applies if you use Gradle to execute such code with JavaExec.
Same applies when running the compiled classes outside of Gradle - the JVM that needs to execute code compiled with preview features needs to receive the --enable-preview flag in order to recognize the bytecode.

For reference: https://docs.gradle.org/current/userguide/building_java_projects.html#sec:feature_preview

@rieske rieske self-assigned this Mar 19, 2021
@big-guy big-guy added this to the 7.0 RC1 milestone Mar 19, 2021
@big-guy
Copy link
Member

big-guy commented Mar 19, 2021

You'll be able to run Gradle with Java 16 in 7.0, but you can already sort of use JDK16 with 6.8.3:

https://melix.github.io/blog/2021/03/gradle-java16.html

We may backport better support for compiling/testing with Java 16 in a future 6.8.x, but you won't be able to run Gradle 6.8.x on Java 16.

@big-guy big-guy closed this as completed Mar 19, 2021
@owo-bot
Copy link

owo-bot commented Mar 20, 2021

This is closed as the last opened ticket for milestone 7.0-RC1. Does that mean this RC version will be available soon?

@carl-mastrangelo
Copy link

@big-guy Java 16 still have some issues even with 7.0-rc-2. #13629 points to here and is closed as a dupe, but that issue is still broken even with the latest RC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:feature A new functionality @core Issue owned by GBT Core
Projects
None yet
Development

No branches or pull requests