@executable_path在Java程序中指向何处 [英] Where does @executable_path point to in a Java program
问题描述
我正在尝试像这样在Mac OS X 10.10.5上的Java中加载本机库:
I'm trying to load a native library in Java on Mac OS X 10.10.5 like this:
System.loadLibrary("SgCore_wrap");
并引发异常:
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
所以我的问题是,如果使用Java程序,@executable_path
指向何处?这取决于我是从命令行运行还是在Eclipse中运行的天气?
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?
此外,假设正确的位置是系统中的某个地方"(例如"/Library"),那么在具有嵌入式JVM的可分发Mac OS捆绑包(.app)中,最好的策略是什么?
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?
我的otool针对涉及的两个库显示的内容(有问题的libSgCore_wrap.dylib中的函数调用libsgCore64.dylib中的函数):
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)
,这里是
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)
作为一个额外的问题,为什么libSgCore_wrap.dylib会引用自身,并且对库应该位于何处意味着什么?
As a bonus question, why does libSgCore_wrap.dylib reference itself and what does it mean/effect as far where the library should be?
推荐答案
似乎您将.dylib
从其他应用程序直接复制到用户文件夹,然后尝试使用Java加载它.
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.
问题在于这些库上的引用使用的是相对于主可执行文件(另一个应用程序)的@executable_path
,并且当Java尝试加载这些库时,使用@executable_path
的引用不正确,因此
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.
针对您的特定情况的可能解决方案是改用@loader_path
,因为此变量是相对于引用二进制文件的.
A possible solution for your specific case is to use @loader_path
instead since this variable is relative to the referring binary.
因此,如果您只需要这两个库,并且可以使用它们的副本而不必担心它们的更新等,并且它们都在同一目录中,那么您可以尝试复制这些库并从中更改它们的引用使用install_name_tool
从@executable_path
到@loader_path
.
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
.
正如您在代码中所示,我想两个库都位于同一路径/Users/nyholku/sgCoreTest/
中,并且由于您使用的是System.loadLibrary
方法,因此您可以正确设置-Djava.library.path=/Users/nyholku/sgCoreTest/
.
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/
.
首先,使用以下命令install_name_tool -change oldReference newReference dylibToChange
将libSgCore_wrap.dylib
文件中对libsgCore64.dylib
的引用更改为您的情况:
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
然后,在您的情况下,必须使用install_name_tool -id newReference dylibToChange
更改libsgCore64.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
现在您可以使用这些修改的库,它们将在Java中正确加载.
Now you can use these modified libraries and they will load correctly in Java.
这篇关于@executable_path在Java程序中指向何处的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!