badass-jlink-plugin icon indicating copy to clipboard operation
badass-jlink-plugin copied to clipboard

JEP 493 / Temurin JDK 24 breaks plugin

Open CodeDead opened this issue 6 months ago • 4 comments

Due to JEP 493, and Temurin implementing this, the jmods folder has been removed from the Temurin / Adopium JDK 24. This causes some issues with this plugin being unable to find modules like 'java.base' when trying to execute the jlink task.

For more info: https://adoptium.net/blog/2025/03/eclipse-temurin-jdk24-JEP493-enabled/

Some of the lines that need changes: https://github.com/beryx/badass-jlink-plugin/blob/fbc426ce9fa4196e6f439a4e8c8d47333c615e0c/src/main/groovy/org/beryx/jlink/impl/JlinkTaskImpl.groovy#L79

Quick search: https://github.com/search?q=repo%3Aberyx%2Fbadass-jlink-plugin%20jmods&type=code

CodeDead avatar Apr 27 '25 23:04 CodeDead

Reference in Adoptium: https://github.com/adoptium/adoptium-support/issues/1271

CodeDead avatar Apr 28 '25 00:04 CodeDead

Thank you for reporting this. I will try to reproduce it later.For the time being, use a JDK that ships with the modules as woRkaround.

xzel23 avatar Apr 28 '25 15:04 xzel23

Hi @xzel23 ,

The workaround is 'simple'. It will make the plugin compile again for the system platform, however, cross-compiling is blocked due to this JEP and using Adoptium 24 at the moment without jmods.

Anyway, the fix: Replace https://github.com/beryx/badass-jlink-plugin/blob/fbc426ce9fa4196e6f439a4e8c8d47333c615e0c/src/main/groovy/org/beryx/jlink/impl/JlinkTaskImpl.groovy#L79 by

if(!new File("$jdkHome/jmods/java.base.jmod").file && JavaVersion.get(jdkHome) < 24) {
  throw new GradleException("java.base module not found in $jdkHome${File.separator}jmods")
}

CodeDead avatar May 04 '25 04:05 CodeDead

Workaround: Use another JDK distribution. We use Zulu and it works.

koppor avatar Jun 04 '25 10:06 koppor

@xzel23 Any progress on this?

msgilligan avatar Aug 06 '25 00:08 msgilligan

The same issue is true for JDK 25 and this is causing a problem for multiple FOSS JavaFX projects where Temurin is the preferred distribution. Is it likely this will be fixed soon?

msgilligan avatar Sep 24 '25 23:09 msgilligan

@msgilligan Hi, I had postponed this because I still need a unit test for this that reproduces the issue. A test case has been announced by the author of the PR but has not been submitted yet, that's why there has been no progress.

xzel23 avatar Sep 24 '25 23:09 xzel23

I think I'd could fairly easily make a standalone repo with GitHub Actions to reproduce the issue. Would that help?

Update: here it is: https://github.com/msgilligan/gradle-jlink-jep-493-sample

msgilligan avatar Sep 25 '25 00:09 msgilligan

Thank you. I'm looking into it. I was traveling for two days to get home and will probably need a day or two to get rid of the jet lag and keeping up with my day job, so don't expect much progress before the weekend is over.

I still think it wasn't the smartest decision of the temurin folks to enable a feature that is explicitly stated as "non default" in the JEP instead of providing a standard build and a supplementary one with the jmods removed for testing and early adopters, and I also still fear that some things might break down the road, but I will try to see if disabling the module check will allow builds to succeed on temurin. If it works, I'll release a new version soon.

xzel23 avatar Sep 25 '25 19:09 xzel23

@msgilligan This is a bit nasty. I have created a unit test case for this that fails (good) and passes after I removed the check for the base jmod (also good). The problem now is: Java 25 (or at least 24) is needed for the test. So I set up the foojay toolchain resolver plugin for that test case - problem is: the plugin does not work on ARM64 (all of Windows, MacOS, and Linux fail with the same error), and I only have an ARM machine. But it works if I have a local temurin 25 installation that the toolchain plugin can see. So I managed to get a working build on my local (MacOS ARM) machine, but building with GitHub actions still fails (all three x64 builds: Window, MacOS, and Linux).

The toolchain resolver should definitely work on all x64 platforms, so there seems to e another problem. Still investigating.

xzel23 avatar Sep 26 '25 16:09 xzel23

Why not add aarch64 instances and jdk 25 to the build matrix on GHA and not use the toolchain resolver plugin? (And you can install multiple JDKs with actions/setup_java such that the first one is used to run Gradle and the second is added to the Gradle toolchains config)

msgilligan avatar Sep 26 '25 16:09 msgilligan

@msgilligan There are always different ways to solve a problem. The reason to use the toolchain resolver plugin was to be able to test locally. Since it doesn't work, I have installed temurin 25 locally and also added the toolchain in the GitHub Actions workflow and now everything passes.

Please try version 3.1.4-rc of the plugin and report back if it works as expected in your case.

xzel23 avatar Sep 27 '25 04:09 xzel23

~~How do I try 3.1.4-rc, do I need to build it from master?~~ I see, it's on the plugin portal (even without a tag on GitHub) -- I will give it a try!

msgilligan avatar Sep 27 '25 15:09 msgilligan

It seems to be working, but I've found some inconsistent behavior in the JDK 24/25 Temurin case that causes the bitcoinj wallettemplate sample app to crash (i.e. Temurin 21 or Zulu 24/25 work fine.) It seems in the Temurin 24/25 case behavior at runtime is more strict, with references from the unmerged module to several modules causing crashes. The fix/workaround is to add the following:

    mergedModule {
        requires 'java.logging'
        requires 'jdk.unsupported'

        requires 'org.slf4j'
    }

Technically (I think) these declarations would be required if two automatic modules being merged were real modules:

  • bitcoinj-core: requires java.logging and org.slf4j
  • com.google.protobuf:protobuf-javalite:4.30.2: requires jdk.unsupported (for unsafe memory access)

So it seems, there is a difference in behavior when BA JLink is using a JEP 493 JDK than a non-JEP 493 JDK. The behavior with JEP 493 might be more correct, but the difference should be noted. (And perhaps the non-493 behavior should be changed to match the 493 behavior.)

I still need to do more testing, but if adding the mergedModule block with the 3 requires directives works with older and non-493 JDKs I will make a PR to make that change in bitcoinj master and I will consider this issue resolved.

But I would like to understand what is going on a little better -- if anyone who understands it better than me can explain it. I think this should documented in a release note and/or in the BA JLink manual. And perhaps the behavior without JEP 493 should be changed (perhaps with an enable/disable flag) to match the JEP 493 behavior.)

I'll post another update after doing additional testing.

Here's the exception from a crash when bitcoinj-core tries to access java.logging:

java.lang.IllegalAccessError: superclass access check failed: class org.bitcoinj.utils.BriefLogFormatter (in module org.bitcoinj.merged.module) cannot access class java.util.logging.Formatter (in module java.logging) because module org.bitcoinj.merged.module does not read module java.logging

msgilligan avatar Sep 27 '25 16:09 msgilligan

I tested building Sparrow Wallet with JDK 25 Temurin and the 3.1.4 RC with Gradle 9.1.0. Everything works correctly, with no changes required to mergedModule. Thanks for the work on this, looking forward to seeing the final release.

craigraw avatar Sep 28 '25 09:09 craigraw

But I would like to understand what is going on a little better -- if anyone who understands it better than me can explain it. I think this should documented in a release note and/or in the BA JLink manual. And perhaps the behavior without JEP 493 should be changed (perhaps with an enable/disable flag) to match the JEP 493 behavior.)

@craigraw @xzel23 Upon further thought and reviewing the BA JLink Manual, I was reminded that when an application is not using the mergedModule block, BA JLink tries to generate one automatically. So it could be that automatic generation of the mergedModule is failing with JEP 493 in cases where it previously worked correctly. The solution for wallettemplate was to add a manual mergedModule block. Sparrow required no changes because it already had one.

So there may still be an issue with JEP 493 that needs to be resolved if you want to support the automatically-generated mergedModule block with JEP 493 distros.

msgilligan avatar Sep 28 '25 15:09 msgilligan