2016-11-07 51 views
1

我试图加载Java中在Mac OS X 10.10.5这样的本地库确实@executable_path点:凡在Java程序

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内运行?

此外,假设正确的位置是'系统中的某个地方',比如说'/ Library',那么最好的策略是在嵌入式JVM的可分发Mac OS包(.app)中处理这个问题?

这就是我otool显示了问题的参与(在libsgCore64.dylib在libSgCore_wrap.dylib调用函数的函数)的两个库:

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)      

这里otool为

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引用它自己以及它在图书馆应该在什么地方意味着什么?

+0

AFAIK @executable_path是实际的可执行文件,即java程序中没有包装程序二进制文件。很无用。上次遇到这样一个库时必须使用DYLD_FALLBACK_LIBRARY_PATH。 – user2543253

+0

这就是我的想法,也想到了DYLD_FALLBACK_LIBRARY_PATH,但现在读取的地方为了安全起见,忽略了所有的DYLD_。 – nyholku

回答

0

看来你是直接从其他应用程序的.dylib的拷贝到你的用户文件夹,然后你想使用Java来加载它。

的问题是,这些库的引用使用@executable_path这是相对于主可执行文件(其他应用程序),当Java的尝试使用@executable_path不正确加载这些库的引用,所以dlopen找不到所需的依赖关系。

为您的特定情况下,一个可能的解决方案是使用@loader_path,而不是因为这个变量是相对于参考二进制文件。

所以,如果你只需要这两个库,并且你可以使用它们的副本而不用担心他们的更新等,并且它们都在同一个目录中,那么你可以尝试复制库并更改它们的引用从@executable_path@loader_path使用install_name_tool

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

首先,改变使用如下命令install_name_tool -change oldReference newReference dylibToChange,你的情况libSgCore_wrap.dyliblibsgCore64.dylib

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

现在你可以使用这些修改过的库和他们W¯¯在Java中正确加载。