I have a dynamic library libOne.dylib
written in Rust and I'd like to call it from Java over JNI. I have the sources for the Rust part but can't change them so I've written a thin C wrapper as the JNI counterpart. I can compile and link my wrapper as libTwo.dylib
and load it into the JVM.
Unfortunately, the next thing the JVM is doing is loading libOne
by looking into the folder where this library was placed during the time it was built so effectively I can't even start my Java application in any other environment without creating the same path where the Rust project is located on my machine and placing the libOne
inside it.
Is it possible to change this behavior so that the library looked for in the same folder as the wrapper? I would prefer to completely embed the libOne
into libTwo
, but I'm not sure if it is possible/feasible. Ideally, I'd like to package the resulting library(ies) directly into the fat jar.
This is how I'm creating the wrapper library.
LIBS="$(pwd)/lib"
gcc \
-dynamiclib \
-shared \
-I$JAVA_HOME/include \
-I$JAVA_HOME/include/darwin \
-I$JAVA_HOME/include/linux \
*.c \
-o $LIBS/libTwo.dylib \
-L$LIBS \
-lOne \
-Wl,-rpath,.
It is placed directly in the Java project's lib
folder but still looks up in the path it was initially built.
The exception looks like following:
java.lang.UnsatisfiedLinkError: /Users/user/LIB-TWO-PROJECT/lib/lobTwo.dylib:
dlopen(/Users/user/LIB-TWO-PROJECT/lib/libTwo.dylib, 1):
Library not loaded: /Users/user/LIB-ONE-PROJECT/target/release/deps/libOne.dylib
Referenced from: /Users/user/LIB-TWO-PROJECT/lib/lobTwo.dylib
Reason: image not found
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
Please note that the path for libOne
is the LIB-ONE-PROJECT release folder (target/release/deps
) and not the LIB-TWO-PROJECT/lib
where both libs are placed.