2

Problem:

  • I wish to run an app written in Java on an M1 Mac (running Monterey 12.0.1, as it happens).
  • The app contains at least one .jar file with a universal mac binary containing only an i86 fork, no arm fork
  • this app worked with the Oracle JRE (Java 8 Update 311)
  • but once I installed Oracle's JDK 17 for Arm 64 (from the .dmg rather than the tarball), launch failed, whether I launched it from the command line (which would definitely be via the SDK) or from Finder as before.
  • In particular, it fails complaining about lack of native arm support.
  • presumably some JRE binary, which tolerated/emulated/expected intel, was replaced by one that demanded ARM.

Desired solution:

  • Ideally, I'd like to be able to build and debug java apps for both intel and M1 macs, and run either type if I downloaded them.
  • Failing that, I'd like to be able to have the appropriate SDK installed for my hardware, and still run intel-only java apps from the JRE.
  • I'd settle for a way to uninstall the SDK and get back to the JRE-only state I had before installing it.

Does anyone know how to accomplish any of these? Oracle's site doesn't even tell me how to uninstall the SDK - just how to install Java entirely.

Bonus if anyone knows how the app developer, who may not even own a mac, can build his app to work natively on both intel and ARM macs, i.e. populate both parts of the mac universal binary.

Edit: responding to the comment below, here's an example of the errors that caused me to believe there was a native component, even though java itself is supposed to be OS and hardware independent.

gluegen_rt appears to be part of the app; in particular, the app checks for a current version of it on start up and downloads it if it doesn't exist. It usually shows up with a name suggesting it's a *.jar, not a lib*.dylib.

java.lang.UnsatisfiedLinkError: /private/var/folders/zk/926c34c13hg6y_y5gyvp7hy40000gn/T/jogamp_0000/file_cache/jln15681904295245521471/jln2148212923575489460/natives/macosx-universal/libgluegen_rt.dylib: dlopen(/private/var/folders/zk/926c34c13hg6y_y5gyvp7hy40000gn/T/jogamp_0000/file_cache/jln15681904295245521471/jln2148212923575489460/natives/macosx-universal/libgluegen_rt.dylib, 0x0001): tried: '/private/var/folders/zk/926c34c13hg6y_y5gyvp7hy40000gn/T/jogamp_0000/file_cache/jln15681904295245521471/jln2148212923575489460/natives/macosx-universal/libgluegen_rt.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/lib/libgluegen_rt.dylib' (no such file)
   at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
   at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:384)
   at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:228)
   at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:170)
   at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2389)
   at java.base/java.lang.Runtime.load0(Runtime.java:755)
   at java.base/java.lang.System.load(System.java:1953)
   at com.jogamp.common.jvm.JNILibLoaderBase.loadLibraryInternal(JNILibLoaderBase.java:604)
   at com.jogamp.common.jvm.JNILibLoaderBase.access$000(JNILibLoaderBase.java:64)
   at com.jogamp.common.jvm.JNILibLoaderBase$DefaultAction.loadLibrary(JNILibLoaderBase.java:107)
   at com.jogamp.common.jvm.JNILibLoaderBase.loadLibrary(JNILibLoaderBase.java:488)
   at com.jogamp.common.os.DynamicLibraryBundle$GlueJNILibLoader.loadLibrary(DynamicLibraryBundle.java:427)
   at com.jogamp.common.os.Platform$1.run(Platform.java:321)
   at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
   at com.jogamp.common.os.Platform.<clinit>(Platform.java:290)
   at com.jogamp.opengl.GLProfile.<clinit>(GLProfile.java:154)
   at haven.JOGLPanel.mkcaps(JOGLPanel.java:73)
   at haven.JOGLPanel.<init>(JOGLPanel.java:93)
   at haven.MainFrame.<init>(MainFrame.java:172)
   at haven.MainFrame.main2(MainFrame.java:445)
   at haven.MainFrame.lambda$main$0(MainFrame.java:481)
   at java.base/java.lang.Thread.run(Thread.java:833)

Here are the launch messages that make me believe gluegen-rt is part of the app.

$ java -jar ~/Downloads/updater-hafen.jar
OS: 'Mac OS X', arch: 'aarch64'
Checking for updates...
Updates found for 'jogl.jar'
Updates found for 'gluegen-rt.jar'
Updates found for 'hafen-res.jar'
Updates found for 'builtin-res.jar'
Updates found for 'hafen.jar'
Updates found for 'client-res.jar'
Downloading 'jogl.jar'
Downloading 'gluegen-rt.jar'
Downloading 'hafen-res.jar'
Downloading 'builtin-res.jar'
Downloading 'hafen.jar'
Downloading 'client-res.jar'
Starting client...
java -Xmx2048m -Dsun.java2d.uiScale.enabled=false -Djava.library.path="%PATH%":. -jar client/hafen.jar -U https://www.havenandhearth.com/res/ game.havenandhearth.com

Other messages that I don't seem to have saved suggested that gluegen-rt.jar contained linux-intel, linux-arm, windows, and mac portions, and that the mac portion was a 'universal' mac binary containing only an intel fork.

4
  • 2
    All the interface with the arhitecture for Java is OS ands CPU independent. ie a pure Java jar will run on Windows Linux or macOS etc and on Arm, Intel and other CPUs. jars do not contain cpu forks. Binaries non jar files will have an archtecture. So you need to give more detail
    – mmmmmm
    Commented Nov 27, 2021 at 23:12
  • Answered at perhaps too much length as an addendum to the question. Commented Nov 27, 2021 at 23:52
  • Ok that error is about a native library but it is not a Java library. It is called by a third party library jogamp.org/gluegen/doc/manual You need to ask their support about it.
    – mmmmmm
    Commented Nov 28, 2021 at 0:02
  • Also not in macOS universal has meant several things over time - all bundling architectures - ppc ppc64 i386 and x86_64 , the last being Intel and now add arm
    – mmmmmm
    Commented Nov 28, 2021 at 0:05

2 Answers 2

4

The issue here is that you are calling a C library via jogamp The C library provided (I think OpenGL) is Intel only.

Oracle's JDK and JRE are not universal (see the downloads page) i.e. they only do one architecture. Similarly the OpenJDKs are not universal.

Thus to run on ARM and Intel you need two different JREs

Pure Java code should run on any operating system (Linux, Solaris, Windows, macOS and others) and on any architecture e.g. Intel, Arm, SPARC. So you only need one jar for all.

The C code could be built universal and your app could be packaged to include both JREs and the launcher (i.e. executable file given in Info.plist) works out from the architecture which JRE to call)

Java 8 worked as it is Intel and so the whole process ran under Rosetta

0

If you install the ARM JDK and find it breaks some app using e.g. gluegen, the simplest solution is to install the Intel JDK.

In particular, if you installed the ARM JDK to the default location using the disk image from Oracle's site, you can do precisely the same thing with the Intel JDK. This will effectively overwrite the ARM JDK.

Don't try simply installing the (Intel) JRE on top of the mess. That does NOT work - the JRE built-into the ARM JDK somehow persists. (And following Oracle's instructions for deleting Java before re-installing the JRE won't help either.)

According to Oracle's site, it's possible in theory to install multiple JDK's each in their own location, and switch between them. That would probably also work, but I haven't tried it.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .