2011-05-14 17 views
1

[最終解決方案可以在接受的答案的評論中找到。由於bmargulies]Java - JNA和共享庫,當從Linux上的.jar開始時出現UnsatisfiedLinkError

嗨夥計們,

我有一個很奇怪的錯誤,我想不出原因。所以這裏是設置:我正在用Java構建一個獨立於平臺的音樂播放器。作爲本機聲音庫,我使用的是irrKlang引擎(http://www.ambiera.com/irrklang/),它分別作爲Windows,Linux和MacOS的一組共享庫。由於這些庫是用C++編寫的,我已經構建了一個共享庫作爲包裝器(也用C++,但使用extern「C」等),也爲每個所需的操作系統編譯。 我現在使用JNA中的包裝器。我使用eclipse,所有需要在項目的主文件夾(當前的工作目錄)庫抵抗。現在問題來了:如果我使用eclipse運行我的Java應用程序,甚至在Windows上構建一個.jar到項目的主文件夾並在那裏執行它都沒有問題,那麼一切正常。但具體是在Linux上,當我包了(!平時工作)應用到一個.jar,我得到以下錯誤:

Exception in thread "main" java.lang.reflect.InvocationTargetException 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:616) 
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) 
Caused by: java.lang.UnsatisfiedLinkError: Unable to load library 'IrrklangWrapper': libIrrKlang.so: cannot open shared object file: No such file or directory 
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:163) 
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:236) 
at com.sun.jna.Library$Handler.<init>(Library.java:140) 
at com.sun.jna.Native.loadLibrary(Native.java:379) 
at com.sun.jna.Native.loadLibrary(Native.java:364) 
at Demo.<init>(Demo.java:29) 
at Demo.main(Demo.java:55) 
... 5 more 

「IrrKlangWrapper」是我自己的共享庫,「libIrrKlang.so」是圖書館由它包裹。所以JNA能夠找到我的圖書館,但我的圖書館無法找到包裝的圖書館。奇怪的!特別是因爲如果我直接啓動項目(無需構建.jar),就不會發生這種情況。

因爲有些人可能會問它,這裏也用C++編寫的代碼 - 儘管我不認爲這個問題的根源就在那裏,作爲引發錯誤所包含的方法被調用之前做:

#include <iostream> 
#include <stdio.h> 
#include <irrKlang.h> 
#include <sys/stat.h> 
#include <string> 
#include <unistd.h> 
using namespace std; 

extern "C" { 

int func(char *path) { 
    cout << path << endl; 

    irrklang::ISoundEngine* engine = irrklang::createIrrKlangDevice(); 
    engine->loadPlugins("./"); 
    cout << engine->getDriverName() << endl; 
    engine->play2D(path); 
    //Endless loop for testing. TODO: Remove 
    while (true) { 
    } 
    engine->drop(); 

    return 0; 
} 
} 

任何人都知道如何解決這個問題?由於我的應用程序打算獨立於平臺,因此我無法將任何共享庫複製到特定文件夾 - 它們必須駐留在我的應用程序的(子)文件夾中。

由於提前,

安德烈

回答

3

在Linux上,你將需要設置LD_LIBRARY_PATH包括含有第二共享庫的目錄。

這個要求很難解決。在Java進程開始時,LD_LIBRARY_PATH只能由ld.so讀取。稍後您無法添加。

您必須創建一個大的共享庫,這意味着要找到.a版本的依賴關係併入其中。

+0

我已經認爲它可能是這樣的。我將如何從C++代碼中執行此操作?而且:爲什麼直接執行時會工作? – 2011-05-14 13:43:21

+0

它真的在linux *上「直接」工作嗎? – bmargulies 2011-05-14 13:48:49

+0

它的確如此。如果我從eclipse中啓動它,則使用項目主文件夾中的共享庫。 – 2011-05-14 13:53:28