@executable_path指向Java程序中的哪个位置

时间:2016-11-07 21:34:17

标签: java macos java-native-interface dylib

我正在尝试在Mac OS X 10.10.5上用Java加载本机库,如下所示:

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

并抛出异常:

@executable_path

所以我的问题是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) 指向Java程序的位置,这取决于我从命令行或Eclipse中运行的天气吗?

此外,假设正确的位置是“系统中的某个位置”,比如说'/ Library',在具有嵌入式JVM的可分发Mac OS捆绑包(.app)中处理此问题的最佳策略是什么?

这是我的otool为所涉及的两个库(libsgCore_wrap.dylib中的函数在libsgCore64.dylib中调用函数)所显示的内容:

 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)

的otool输出
{{1}}

作为一个额外的问题,为什么libSgCore_wrap.dylib引用自身以及它到库的位置是什么意思/影响?

1 个答案:

答案 0 :(得分:0)

似乎您将.dylib从其他应用程序直接复制到您的用户文件夹,然后您尝试使用Java加载它。

问题是这些库上的引用使用的@executable_path是相对于主可执行文件(另一个应用程序)的,当Java尝试加载这些库时,使用@executable_path的引用不正确,因此dlopen无法找到所需的依赖项。

针对您的具体情况的可能解决方案是使用@loader_path,因为此变量与引用二进制文件相关。

因此,如果您只需要这两个库,并且可以使用它们的副本而不必担心它们的更新等,并且两者都在同一目录中,那么您可以尝试复制库并更改它们的引用使用@executable_path @loader_pathinstall_name_tool。{/ p>

正如您在代码中显示的那样,我认为这两个库位于同一路径/Users/nyholku/sgCoreTest/,并且由于您使用的是System.loadLibrary方法,因此您正确设置-Djava.library.path=/Users/nyholku/sgCoreTest/

首先,在您的情况下,使用以下命令libSgCore_wrap.dyliblibsgCore64.dylib更改为install_name_tool -change oldReference newReference dylibToChange

install_name_tool -change @executable_path/../Frameworks/libsgCore64.dylib @loader_path/libsgCore64.dylib libSgCore_wrap.dylib

然后,在您的情况下,您必须使用libsgCore64.dylib更改install_name_tool -id newReference dylibToChange的标识符:

install_name_tool -id @loader_path/libsgCore64.dylib libsgCore64.dylib

现在您可以使用这些已修改的库,它们将在Java中正确加载。