我正在使用JNA和Java,但我认为这个问题会影响任何本地到非本地的桥梁。
我有一个依赖lib1.dylib的Java应用程序,而lib1.dylib依赖于lib2.dylib。
我想把我的.app文件中的所有内容都放在Mac上。我可以轻松地将lib1.dylib放入其中并设置java.classpath(或NativeLibrary.addSearchPath())以告诉JVM在哪里可以找到lib1.dylib。问题是,我不知道如何沟通lib1.dylib的依赖关系也在我提供的位置。结果是lib1加载正常,但是找不到lib2,因为它不在操作系统的库路径中。
任何人都知道如何克服这个问题?我想在包含大量共享库的大型项目中必须有很多。
答案 0 :(得分:2)
我之前遇到过这个问题,今天又遇到了这个问题。您可以通过添加VM参数“-Djava.library.path = / path / to / other / libs”来绕过它,但我似乎记得Java只使用它来搜索初始库,然后使用系统PATH查找任何依赖项。
我之前尝试过的一些解决方案:
1)在加载库之前,在依赖库上使用System.load(absolutePath)。不会让你的程序超便携,除非你总是知道那个库的位置。
2)在lib1依赖于lib2的情况下,我实际上在链接到任何依赖库之前在本机代码中使用了SetCurrentDirectory(Windows,不确定Mac等价物),这似乎有效。同样,需要知道其他库的位置。
3)在Windows上,可以将依赖库转储到c:\ windows \ system32中,然后找到它们。
关于类似主题的一些有用的帖子(特定于Windows,但我认为问题是相同的):
http://www.realityinteractive.com/rgrzywinski/archives/000219.html http://www.velocityreviews.com/forums/t387618-jni-library-path.html
答案 1 :(得分:0)
我已经根据Stew中的(2)中的想法找到了MacOSX的解决方案:
使用Mac的JarBundler(或同名的Ant任务)将workingdirectory变量设置为$ JAVAROOT,并确保您的dylib位于.app的Contents / Resources / Java部分。如果这样做,动态链接器将找到所有依赖项dylib,因为它将是当前目录。由于同样的原因,Java也会找到原始的dylib(具有所有依赖关系的dylib)。
Ant代码:
<target name="package_mac_app" depends="package_jar, compile_native" description="bundle the runnable jar into a Mac Application -- requires JarBundler ANT Task">
<taskdef name="jarbundler" classname="net.sourceforge.jarbundler.JarBundler"/>
<echo message="CREATING MAC .app EXECUTABLE"/>
<jarbundler dir="${dist}"
name="${appname}"
mainclass="myPackage.myMainClass"
icon="${icon_location}"
jvmversion="1.5+"
infostring="${appname}"
shortname="${appshortname}"
bundleid="${com.mycompany.mydepartment.myprogram}"
jar="${run_jar_location}"
workingdirectory="$JAVAROOT">
<javafilelist dir="${dylib_location}" files="my-lib.dylib"/>
<javafilelist dir="${dylib_location}" files="dependent-lib.dylib"/>
</jarbundler>
</target>