I have built a Java application that is bundled with universal binaries for the Java Runtime Environment, so that the application can run natively on both x86_64 and arm64 machines.
That is, the executable file within the application is a shell script that calls the embedded java
binary to actually start the Java program. The java
binary itself is a “universal binary” created with lipo
, with support for both x86_64 and arm64.
Trying to start the application from the command line, with open -a MyApplication.app
, on my M1-powered machine yields the expected behaviour: the application is running natively, as can be seen in the Activity Monitor, where the corresponding process is shown as running under an “Apple” CPU kind. (It can also be seen by the mere fact that the application is much more responsive than it is when it is executed by a x86_64 JRE).
However, when the very same application is executed from the Finder, by double-clicking on MyApplication.app
, it then runs under x86_64 emulation, as can be seen in the Activity Monitor, where the corresponding process is shown as running under an “Intel” CPU kind.
How comes that the same application runs under emulation or not depending on whether it is started from the command line or from the Finder? How can I force the application to run natively when it is started from the Finder?
Adding the LSRequiresNativeExecution
key in the Info.plist
file does not change anything, nor does adding the LSArchitecturePriority
key.
My workaround for now is to build two variants of my application, one with a x86_64 JRE for Intel users and one with a arm64 JRE for my Apple Silicon users. But I’d really like to be able to provide them with a single application that runs natively on both architectures.
Any help welcome. Happy to provide more details if needed.