2010-03-24 67 views
0

我正在使用JNA和Java,但我认为这个问题会影响任何本地到外部的桥。搜索路径,其中一个本地库依赖于另一个本地库

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

我想把我的.app文件放在Mac里面。我可以很容易地将lib1.dylib放在里面,并设置java.classpath(或NativeLibrary.addSearchPath())来告诉JVM在哪里找到lib1.dylib。麻烦的是,我不知道如何通知lib1.dylib的依赖关系也在我提供的位置。结果是lib1加载正常,但是因为lib2不在操作系统的库路径中,所以找不到lib2。

任何人都知道我能克服这个问题吗?我认为它必须在大量共享库的大型项目中大量出现。

回答

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

+0

谢谢!我会检查出来的。对不起,我的问题中混淆了classpath和java库路径。 (1)或(2)可能值得丢失便携性。我试图避免(3),因为它使安装程序非常复杂,需要root访问权限,覆盖其他应用程序需要的现有旧版本库的风险等。 - - – 2010-03-24 23:04:13

+0

调查完这些选项之后,只有坏消息。 (1)不适用于JNA。显然,JNA并不关心Java是否曾经加载过这个库,大概是因为它必须自己做映射的东西。但它会与JNI一起工作。(2)需要针对不同操作系统的特殊代码,但最大的问题是,在UNIX中没有与dllmain等价的东西,并且没有特别的保证(我知道)在依赖查找完成之前将执行cwd开关。 我看不出(3),我试图避免这个问题。游民。 – 2010-03-25 03:34:31

0

我发现基于这样的思想为MacOSX的解决方案(2)from炖:

使用Mac的JarBundler(或同名的Ant任务)将workingdirectory变量设置为$ JAVAROOT并确保您的dylib位于.app的Contents/Resources/Java部分。如果你这样做,动态链接器将会找到所有依赖dylibs,因为它将成为当前目录。由于同样的原因,Java也会找到原始的dylib(具有所有依赖关系的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> 
+0

不错。我可能会在我的一个项目中尝试这个。它非常干净,仍然适合整个“拖放式安装”。 – Stew 2010-03-25 20:48:45

相关问题