简体   繁体   English

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

[英]Java - JNA and shared Libraries, UnsatisfiedLinkError when starting from a .jar on Linux

[Final Solution can be found in the comments to the accepted answer. [最终解决方案可以在接受答案的注释中找到。 Thanks to bmargulies] 感谢bmargulies]

Hey Folks, 嘿伙计,

I've got a quite weird error and I can't figure out the reason. 我有一个很奇怪的错误,我不知道原因。 So here's the setup: I'm building a platform-independent music player in Java. 设置如下:我正在用Java构建与平台无关的音乐播放器。 As native sound library I'm using the irrKlang engine ( http://www.ambiera.com/irrklang/ ), which comes as a set of shared libraries for Windows, Linux and MacOS, respectively. 作为本机声音库,我使用的是irrKlang引擎( http://www.ambiera.com/irrklang/ ),该引擎分别是针对Windows,Linux和MacOS的一组共享库。 Since these libraries are written in C++, I've built a shared library as wrapper (also in C++, but using extern "C" and so on), also compiled for each operating system needed. 由于这些库是用C ++编写的,因此,我已经建立了一个作为包装器的共享库(也使用C ++,但使用extern“ C”等),还为所需的每个操作系统进行了编译。 I now use that wrapper out of JNA. 我现在使用JNA的包装器。 I'm using eclipse, all needed library resist in the Project's main folder (the current working directory). 我正在使用Eclipse,所有必需的库抵抗都位于项目的主文件夹(当前工作目录)中。 Now here comes the problem: Everything works fine if I run my Java application out of eclipse and even building a .jar on Windows into the Project's main folder and executing it there brings no problems. 现在出现了问题:如果我在eclipse之外运行Java应用程序,甚至在Windows上将.jar构建到Project的主文件夹中,然后在其中执行该程序,都不会出现任何问题。 But specifically on Linux, when I pack the (usually working!) application into a .jar, I get the following error: 但是特别是在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" is my own shared library, "libIrrKlang.so" is the library wrapped by it. “ IrrKlangWrapper”是我自己的共享库,“ libIrrKlang.so”是它包装的库。 So JNA is able to find my library, but my library isn't able to find the wrapped one. 因此,JNA可以找到我的库,但是我的库无法找到包装的库。 Weird! 奇怪的! Especially because this doesn't happen if I start the Project directly (without building a .jar). 特别是因为如果我直接启动项目(而不构建.jar),则不会发生这种情况。

Because some of you might ask for it, here also the code written in C++ - although I don't think the source of the problem is located there, as the error is raised before the contained method is called: 因为你们中的某些人可能会要求这样做,所以这里也是用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;
}
}

Anyone got an idea how to solve this? 有人知道如何解决这个问题吗? As my application intends to be platform independent, I'm not able to copy any shared libraries to specific folders - they have to reside in a (sub-)folder of my application. 由于我的应用程序打算独立于平台,因此我无法将任何共享库复制到特定的文件夹-它们必须驻留在我的应用程序的(子)文件夹中。

Thanks in advance, 提前致谢,

André 安德烈

On Linux you'll need to set LD_LIBRARY_PATH to include the directory containing that second shared library. 在Linux上,您需要设置LD_LIBRARY_PATH以包括包含第二个共享库的目录。

This requirement is very hard to get around. 这个要求很难解决。 LD_LIBRARY_PATH is only read by ld.so at the inception of the java process. LD_LIBRARY_PATH仅在java进程开始时由ld.so读取。 You can't add to it later. 您以后无法添加。

You have to make one big shared lib, which means finding .a versions of your dependencies to incorporate into it. 您必须创建一个大的共享库,这意味着找到依赖项的.a版本以将其合并到其中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM