badass-jlink-plugin
badass-jlink-plugin copied to clipboard
JEP 493 / Temurin JDK 24 breaks plugin
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
Reference in Adoptium: https://github.com/adoptium/adoptium-support/issues/1271
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.
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")
}
Workaround: Use another JDK distribution. We use Zulu and it works.
@xzel23 Any progress on this?
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 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.
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
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.
@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.
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 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.
~~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!
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: requiresjava.loggingandorg.slf4jcom.google.protobuf:protobuf-javalite:4.30.2: requiresjdk.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
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.
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.