All of the steps below were tested on an Intel Mac running Big Sur.
Download and extract your zulu JDK and point these variables to it:
export ARM64=${PWD}/zulu17.0.13-ea-jdk17.0.0-ea.2-macosx_aarch64
export AMD64=${PWD}/zulu17.0.13-ea-jdk17.0.0-ea.2-macosx_x64
export BUILD=${PWD}
export UJDK=${PWD}/ujdk
Find native binary files from the x86-64 version and save file names of binaries and non-binaries to temporary text files. The x86-64 version serves as a template.
pushd "${AMD64}"
find zulu-17.jdk/Contents -type f -print0 | \
sort -z | \
xargs -0 -n1 -P1 file > "${BUILD}/__files_and_types.txt"
grep -v ': Mach-O.*x86_64$' "${BUILD}/__files_and_types.txt" | \
cut -d: -f1 > "${BUILD}/__non_binary_files.txt"
grep ': Mach-O.*x86_64$' "${BUILD}/__files_and_types.txt" | \
cut -d: -f1 > "${BUILD}/__binary_files.txt"
# Copy non-binaries
while read line; do \
mkdir -p "${UJDK}/$(dirname "${line}")"; \
cp "${line}" "${UJDK}/$(dirname "${line}")"; \
done < "${BUILD}/__non_binary_files.txt"
popd
For all the regular native binaries, merge them to create Universal 2 Binaries.
while read line; do \
mkdir -p "${UJDK}/$(dirname "${line}")"; \
lipo -create \
-output "${UJDK}/${line}" \
"${AMD64}/${line}" \
"${ARM64}/${line}"; \
done < "${BUILD}/__binary_files.txt"
Java modules also contain binary files embedded in their *.jmod
files. For
instance, the packaging tool contains a single-arch launcher binary.
Hence, we need to extract those, to and re-combine those binaries that occur
in both x86-64 and AArch64 architecture builds.
Extract:
pushd "${AMD64}/jmods"
for m in *.jmod; do \
mkdir -p "${BUILD}/jmod/amd64/${m/.jmod/}"; \
"${AMD64}/bin/jmod" extract --dir "${BUILD}/jmod/amd64/${m/.jmod/}" "${m}"; \
done
popd
pushd "${ARM64}/jmods"
for m in *.jmod; do \
mkdir -p "${BUILD}/jmod/arm64/${m/.jmod/}"; \
"${AMD64}/bin/jmod" extract --dir "${BUILD}/jmod/arm64/${m/.jmod/}" "${m}"; \
done
popd
Again, gather file lists and classify into binaries and non-binaries.
pushd "${BUILD}/jmod/amd64"
find . -type f -print0 | \
sort -z | \
xargs -0 -n1 -P1 file > "${BUILD}/jmod/__files_and_types.txt"
grep -v ': Mach-O.*x86_64$' "${BUILD}/jmod/__files_and_types.txt" | \
cut -d: -f1 > "${BUILD}/jmod/__non_binary_files.txt"
grep ': Mach-O.*x86_64$' "${BUILD}/jmod/__files_and_types.txt" | \
cut -d: -f1 > "${BUILD}/jmod/__binary_files.txt"
while read line; do \
mkdir -p "${BUILD}/jmod/ujdk/$(dirname "${line}")"; \
cp "${line}" "${BUILD}/jmod/ujdk/$(dirname "${line}")"; \
done < "${BUILD}/jmod/__non_binary_files.txt"
popd
Re-combine into Universal 2 BinariesL
while read line; do \
mkdir -p "${BUILD}/jmod/ujdk/$(dirname "${line}")"; \
lipo -create \
-output "${BUILD}/jmod/ujdk/${line}" \
"${BUILD}/jmod/amd64/${line}" \
"${BUILD}/jmod/arm64/${line}"; \
done < "${BUILD}/jmod/__binary_files.txt"
Use the jmod
tool to package the Java modules again and move the resulting
modules into place.
pushd "${BUILD}/jmod/ujdk/"
for m in *; do \
(cd "${m}"; "${AMD64}/bin/jmod" create \
--class-path classes \
$([ -d bin ] && echo --cmds bin) \
$([ -d conf ] && echo --config conf) \
$([ -d include ] && echo --header-files include) \
$([ -d legal ] && echo --legal-notices legal) \
$([ -d lib ] && echo --libs lib) \
$([ -d man ] && echo --man-pages man) \
"${BUILD}/jmod/${m}.jmod"); \
done
popd
mv "${BUILD}/jmod/"*.jmod "${UJDK}/zulu-17.jdk/Contents/Home/jmods/"
The ${UJDK}
directory now contains a "Universal JDK". There are some
caveats:
- I haven't been able to make Java packager work -- the resulting packages won't load on M1 Macs.
- You may need to an add additional code-signing step before packaging everything up again
- The resulting JDK will need to be re-notarized as well
% file ${UJDK}/zulu-17.jdk/Contents/Home/bin/java
ujdk/zulu-17.jdk/Contents/Home/bin/java: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
ujdk/zulu-17.jdk/Contents/Home/bin/java (for architecture x86_64): Mach-O 64-bit executable x86_64
ujdk/zulu-17.jdk/Contents/Home/bin/java (for architecture arm64): Mach-O 64-bit executable arm64