问题
I'm trying to load a native library in Java on Mac OS X 10.10.5 like this:
System.loadLibrary("SgCore_wrap");
and it throws an exception:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /Users/nyholku/sgCoreTest/libSgCore_wrap.dylib: dlopen(/Users/nyholku/sgCoreTest/libSgCore_wrap.dylib, 1): Library not loaded: @executable_path/../Frameworks/libsgCore64.dylib
So my question is where does @executable_path
points to in case of a Java program and does this depend on weather I run from command line or within Eclipse?
And further, supposing the correct location is 'somewhere in the system' like say '/Library', what is the best strategy handle this in a distributable Mac OS bundle (.app) with embedded JVM?
This what my otool shows for the two libraries involved (functions in libSgCore_wrap.dylib call functions in libsgCore64.dylib) in question:
otool -L /Users/nyholku/sgCoreTest/libSgCore_wrap.dylib
/Users/nyholku/sgCoreTest/libSgCore_wrap.dylib:
libSgCore_wrap.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 104.1.0)
@executable_path/../Frameworks/libsgCore64.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)
and here otool output for the
tool -L /Users/nyholku/sgCoreTest/libsgCore64.dylib
/Users/nyholku/sgCoreTest/libsgCore64.dylib:
@executable_path/../Frameworks/libsgCore64.dylib (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 157.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.14.0)
As a bonus question, why does libSgCore_wrap.dylib reference itself and what does it mean/effect as far where the library should be?
回答1:
Seems that you copy directly the .dylib
s from some other application to your user folder and then you're trying to load it with Java.
The problem is that the references on these libraries are using @executable_path
which is relative to the main executable (the other application) and when Java try to load these libraries the reference using @executable_path
are not correct, so dlopen
can not find the required dependencies.
A possible solution for your specific case is to use @loader_path
instead since this variable is relative to the referring binary.
So if you only need this two libraries, and you can work with a copy of them without worrying about update on theirs etc, and both are on the same directory, then you can try to copy the libraries and change their references from @executable_path
to @loader_path
using install_name_tool
.
As you show in your code I suppose that both libraries are in the same path /Users/nyholku/sgCoreTest/
and since you're using System.loadLibrary
method you're setting correctly -Djava.library.path=/Users/nyholku/sgCoreTest/
.
First, change the reference to libsgCore64.dylib
inside libSgCore_wrap.dylib
file using the follow command install_name_tool -change oldReference newReference dylibToChange
, in your case:
install_name_tool -change @executable_path/../Frameworks/libsgCore64.dylib @loader_path/libsgCore64.dylib libSgCore_wrap.dylib
Then you must change the identifier of the libsgCore64.dylib
itself, using install_name_tool -id newReference dylibToChange
, in your case:
install_name_tool -id @loader_path/libsgCore64.dylib libsgCore64.dylib
Now you can use these modified libraries and they will load correctly in Java.
来源:https://stackoverflow.com/questions/40475065/where-does-executable-path-point-to-in-a-java-program