Java - JNA和共享库,从Linux上的.jar启动时出现UnsatisfiedLinkError

时间:2011-05-14 13:37:20

标签: java c++ shared jna

[最终解决方案可以在对已接受答案的评论中找到。感谢bmargulies]

嘿伙计,

我有一个非常奇怪的错误,我无法弄清楚原因。所以这就是设置:我正在用Java构建一个独立于平台的音乐播放器。作为原生声音库,我使用irrKlang引擎(http://www.ambiera.com/irrklang/),它分别作为Windows,Linux和MacOS的一组共享库。由于这些库是用C ++编写的,我构建了一个共享库作为包装器(也在C ++中,但使用extern“C”等),也为所需的每个操作系统编译。 我现在使用JNA的包装器。我正在使用eclipse,在Project的主文件夹(当前工作目录)中所有需要的库抵制。现在问题就出现了:如果我从Eclipse中运行我的Java应用程序,甚至在Windows上将.jar构建到Project的主文件夹中并执行它就没有任何问题。但特别是在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;
}
}

任何人都知道如何解决这个问题?由于我的应用程序打算独立于平台,我无法将任何共享库复制到特定文件夹 - 它们必须驻留在我的应用程序的(子)文件夹中。

提前致谢,

安德烈

1 个答案:

答案 0 :(得分:3)

在Linux上,您需要设置LD_LIBRARY_PATH以包含包含该第二个共享库的目录。

这个要求很难解决。 LD_LIBRARY_PATH仅在java进程启动时由ld.so读取。你以后不能添加它。

你必须创建一个大的共享库,这意味着要找到你的依赖项的一个版本。