How to build a JDK on ARM-based Mac
I was exploring how to build a slimmer non-JIT JDK to be embedded in a Desktop app on Apple Silicons Mac.
To conclude, it doesn't seem we can completely disable JIT... or at least the JIT definition by Apple. There is a zero variant JDK [1], which will disable the JVM features: compiler1
and compiler2
and these 2 features are JIT compilers. However, it seems Apple has a different definition of JIT. In essence, Apple wants to forbid invoking pthread_jit_write_protect_np(0)
, which can be used for granting the access to write code "on-the-fly". JDK invokes pthread_jit_write_protect_np(0)
regardless of the variant and will crash if com.apple.security.cs.allow-jit
isn't enabled.
However, the journey of building an old JDK on a new Mac and MacOS is quite challenging, so I wanted summarize the steps in case it is useful for anyone else.
1: Install an older XCode/Clang
The first thing to understand is that an old JDK requires an old Clang. Here's the reference page: https://wiki.openjdk.org/display/Build/Supported+Build+Platforms
If I want to build a JDK 21, then I will need XCode/Clang 13.1. Note that XCode/Clang 12.4 doesn't work on Mac 15.6 anymore.
You can go download older XCode/Clangs here: https://developer.apple.com/download/all/?q=13.4
Here are the steps:
- Rename
Applications/Xcode.app
to/Applications/Xcode_orig.app
for safe-keeping. - Download
Xcode 13.4.1.xip
, unzip, renameXcode.app
toXcode_13.app
, and moveXcode.app
to/Applications
. - Open Terminal and runs:
sudo xcode-select --switch /Applications/Xcode_13.app/Contents/Developer
. - Run
clang --version
to verify that we are using the version 13.
If you don't downgrade Xcode/Clang, you might encounter tons of compilation errors that are obscure. Because Clang 17 (the current version as of now) uses a different standard from Clang 13. Here's one of the error you may encounter:
/Users/tanin/projects/jdk/src/java.base/share/native/libzip/zlib/zutil.h:194:11: error: 'OS_CODE' macro redefined [-Werror,-Wmacro-redefined]
194 | # define OS_CODE 19
| ^
/Users/tanin/projects/jdk/src/java.base/share/native/libzip/zlib/zutil.h:165:11: note: previous definition is here
165 | # define OS_CODE 7
| ^
1 error generated.
This is because a newer Clang decides that macro-redefined
is now not ok.
2: Get JDK and compile
Here's official guide: https://github.com/openjdk/jdk/blob/jdk-22-ga/doc/building.md
You can get the JDK source code by cloning: https://github.com/openjdk/jdk.git
You can switch to the version that you want. For example, 21 would be jdk-21-ga
, so I would run git checkout jdk-21-ga
.
Now you can run bash configure --with-jvm-variants=zero
. This is configured to build the zero variant.
Next you will run make images
in order to build the JDK.
At this step, you might encounter another obscure error:
xattr: [Errno 13] Permission denied: '/Users/tanin/projects/jdk/build/macosx-aarch64-zero-release/jdk/conf/management/jmxremote.password.template'
I have no idea why this happens but hey let's solve it the hacky way by getting the file from somewhere, and here's how you do it:
cp src/jdk.management.agent/share/conf/jmxremote.password.template build/macosx-aarch64-zero-release/jdk/conf/management/jmxremote.password.template
Now you will run make images
again. It will run for a while and fail with the below error:
xattr: [Errno 13] Permission denied: '/Users/tanin/projects/jdk/build/macosx-aarch64-zero-release/images/jdk-bundle/jdk-21.jdk/Contents/Home/legal/java.base/LICENSE'
xattr: [Errno 13] Permission denied: '/Users/tanin/projects/jdk/build/macosx-aarch64-zero-release/images/jdk-bundle/jdk-21.jdk/Contents/Home/legal/java.base/ADDITIONAL_LICENSE_INFO'
xattr: [Errno 13] Permission denied: '/Users/tanin/projects/jdk/build/macosx-aarch64-zero-release/images/jdk-bundle/jdk-21.jdk/Contents/Home/legal/java.base/ASSEMBLY_EXCEPTION'
This error doesn't seem to matter because your JDK would already be built at ./build/macosx-aarch64-zero-release/jdk
.
If you are using SDKMan, you can install your custom JDK with: sdk install java jdk-21-zero ./build/macosx-aarch64-zero-release/jdk
.
And that's how you build a JDK on an Apple Silicon Mac.
[1] Here's some explanation on JDK variants: https://metebalci.com/blog/demystifying-the-jvm-jvm-variants-cppinterpreter-and-templateinterpreter/