A GitHub Actions workflow that builds a universal (Apple Silicon + Intel) Java runtime for macOS from Eclipse Temurin releases.
Adoptium publishes separate macOS builds for aarch64 and x64. If you bundle a Java runtime in a macOS app, you need one for each architecture or a single fat binary. This project makes the fat binary. It merges the two builds into one runtime bundle whose native executables and libraries contain both arm64 and x86_64 slices.
The workflow is in .github/workflows/build.yml and has two jobs.
-
Download (runs once per architecture)
- Downloads the Temurin JDK for the selected release from the Adoptium API (
/v3/binary/version/<release>/mac/<arch>/jdk/hotspot/normal/eclipse). - Extracts it and caches it under the key
<release>-<arch>, so later runs skip the download.
- Downloads the Temurin JDK for the selected release from the Adoptium API (
-
Create Universal Binary
- Restores both cached JDKs.
- Runs
jlinkon each JDK to make a smaller runtime image (--add-modules ALL-MODULE-PATH --strip-debug --no-man-pages --no-header-files --compress=2). The image replacesContents/Home. - Copies both bundles into one output directory with
ditto, so files that exist in only one of them are kept. - Uses
lipoto merge every Mach-O file underContents/MacOS,Contents/Home/binandContents/Home/libinto a universal binary. - Changes
Contents/Home/releasesoOS_ARCHreadsx86_64+arm64. - Zips the result as
<release>-universal.zip, uploads it as a workflow artifact, and creates a build provenance attestation for it.
- Go to Actions → Build Universal Java Runtime in this repository.
- Click Run workflow and fill in the inputs:
- JDK Release: a Temurin release tag such as
jdk-21.0.9+10. - JDK Architectures: a JSON array. The default is
["aarch64","x64"]. Keep this order, because the merge step treats the first entry as arm64 and the second as x86_64.
- JDK Release: a Temurin release tag such as
- When the run finishes, download the
<release>artifact from the run summary. It contains<release>-universal.zip.
You can also start a build with the GitHub CLI:
gh workflow run build.yml -R iterate-ch/universal-macos-java-runtime -f release=jdk-21.0.9+10Check the provenance attestation of a downloaded archive:
gh attestation verify jdk-21.0.9+10-universal.zip -R iterate-ch/universal-macos-java-runtimeCheck that a binary contains both architectures:
lipo -archs jdk-21.0.9+10-universal/Contents/Home/lib/server/libjvm.dylibThe selectable releases are a fixed list in the release input of the workflow. To add one, add its Temurin release name (as shown on adoptium.net, e.g. jdk-25.0.3+9) to on.workflow_dispatch.inputs.release.options in .github/workflows/build.yml.
- The output is a
jlinkruntime image, not the original JDK distribution. Debug symbols, man pages and header files are removed. - The workflow does not code sign the merged bundle. If you embed it in a macOS application, sign it (and notarize the app) with your own Developer ID.