2010-03-24 41 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

相關問題