0

我正在使用 JNA 和 Java,但我认为这个问题会影响任何本地到非本地的桥梁。

我有一个依赖 lib1.dylib 的 Java 应用程序,而 lib1.dylib 依赖于 lib2.dylib。

我想将所有内容都放在 Mac 上的 .app 文件中。我可以轻松地将 lib1.dylib 放入其中并设置 java.classpath(或 NativeLibrary.addSearchPath())来告诉 JVM 在哪里可以找到 lib1.dylib。问题是,我不知道如何传达 lib1.dylib 的依赖项也在我提供的位置。结果是 lib1 加载正常,但随后找不到 lib2,因为它不在操作系统的库路径中。

任何人都知道我可以如何克服这个问题?我想它一定会出现在拥有大量共享库的大型项目中。

4

2 回答 2

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

于 2010-03-24T22:48:43.897 回答
0

我根据 Stew (2) 中的想法找到了 MacOSX 的解决方案:

使用 Mac 的 JarBundler(或同名的 Ant 任务)将工作目录变量设置为 $JAVAROOT 并确保您的 dylib 位于 .app 的 Contents/Resources/Java 部分中。如果您这样做,动态链接器将找到所有依赖 dylib,因为它将是当前目录。出于同样的原因,Java 也会找到原始的 dylib(具有所有依赖项的那个)。

蚂蚁代码:

<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>
于 2010-03-25T18:52:01.060 回答