Try System.loadLibrary before trying to extract native libraries from a JAR
See original GitHub issueWe use Realm in a multi-platform compose app, one that includes a compose desktop build. Some JVM installers move native shared/JNI libraries are out of the JAR, for a number of reasons, including Windows and macOS security systems’ requirement to verify all native code is signed. Conveyor specifically recommends:
Therefore your software should always attempt to load shared libraries by using System.loadLibrary first, before trying to extract native libraries from a JAR. Alternatively you can use System.load in combination with the java.home system property but remember to add either lib on UNIX or bin on Windows.
From what i can see here, it seems Realm will only use System.loadLibrary
on Android, which results in exception when trying to initialize our app on desktop JVM apps:
Caused by: java.lang.RuntimeException: Couldn't load Realm native libraries
at io.realm.kotlin.internal.interop.realmc.<clinit>(realmc.java:28)
... 85 more
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at io.realm.kotlin.internal.interop.realmc.<clinit>(realmc.java:26)
... 85 more
Caused by: java.lang.NullPointerException: lib must not be null
at io.realm.kotlin.jvm.SoLoader.unpackAndInstall(SoLoader.kt:98)
at io.realm.kotlin.jvm.SoLoader.load(SoLoader.kt:62)
at io.realm.kotlin.jvm.SoLoader.load(SoLoader.kt:47)
... 90 more
Issue Analytics
- State:
- Created a year ago
- Comments:9
Top GitHub Comments
I think if you try loadLibrary first users won’t even need to know, right? If it doesn’t work you’ll do what you’re doing now with extraction from the JAR and everything will be just as it was. It only makes a difference if the user or a tool has done the extraction and placement.
Hiya,
The issue here isn’t really Conveyor specific. Rather, anyone who wants to package Realm with their (desktop) app and use jlink to create a bundled JVM setup will hit the issue.
In a completely normal, old-school JVM bundling setup all shared libraries are placed in the library search path by default, so when the JVM executes
System.loadLibrary("foo")
will work without the app needing to care about file locations, caches, extraction from jars etc. That’s why the JDK’s own libraries don’t need to be extracted to your home directory: they’re already next tolibjvm
and so get found correctly. On Windows this means in the samebin
directory, on macOS in theContents/runtime/Contents/Home/lib
directory and so on. Doing things the standard way has many advantages for end users, like not cluttering their home directory, better startup time, better compatibility with code signing and so on.Therefore, Realm should really be compatible with this setup and the good news is how easy it is: just run
System.loadLibrary
always, and continue along the existing codepaths from a catch block. If the library can’t be loaded then you conclude you’re in a developer environment and it’s OK to go unpack to the user’s home dir. If it can be loaded, happy days, you’re running in an end-user package where everything is already laid out properly ahead of time.Does that make sense?