简体   繁体   English

我应该如何为JNI加载本机库以避免出现UnsatisfiedLinkError?

[英]How should I load native libraries for JNI to avoid an UnsatisfiedLinkError?

I want to use JNI on Ubuntu 8.10, using Eclipse and gcc (the standard one with Ubuntu if there are flavours). 我想在Ubuntu 8.10上使用JNI,使用Eclipse和gcc(如果有风味,则使用Ubuntu的标准版)。

I can't seem to load my library despite the make file creating it successfully. 尽管make文件成功创建,我似乎无法加载我的库。

The main Java class is as follows: 主要的Java类如下:

class Hello {
    public native void sayHello();

    static {
        System.loadLibrary("hello.so");
    }

    public static void main(String[] args) {
        Hello h = new Hello();
        h.sayHello();
    }
}

My make file is as such; 我的make文件是这样的;

    all : hello.so

hello.so : Hello.o
    gcc -shared -o hello.so Hello.o

Hello.o : Hello.c Hello.h
    gcc -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux -c Hello.c -o Hello.o

Hello.h : Hello.class
    javah -jni Hello

clean :
    -del Hello.h
    -del Hello.o

The rest of the code (Hello.c) looks like one would think. 其余的代码(Hello.c)看起来像人们想的那样。

The error I'm getting is as follows; 我得到的错误如下;

Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello.so in java.library.path

If I use an explicit path: 如果我使用显式路径:

System.loadLibrary("/home/gavin/Work/workspace/JNI/hello.so");

Then it works, but I'd much rather not use an explicit path if possible. 然后它可以工作,但如果可能的话,我宁愿不使用显式路径。

As per Pax you should set the library path to where ever Java should look for the library. 根据Pax,您应该将库路径设置为Java应该查找库的位置。 Your library name should be libhello.so. 您的库名应该是libhello.so。 The call to load the library should then be: 然后,加载库的调用应该是:

System.loadLibrary("hello");

Linux libraries are referenced by the convention lib name .so and loaded based on the name. Linux库由常规lib 名称 .so引用,并根据名称加载。 Here is a link about dynamic linking problems in Java from the SWIG documentation, although you are not using SWIG this section is still relevant. 以下是SWIG文档中关于Java中动态链接问题的链接 ,尽管您没有使用SWIG,但本节仍然具有相关性。

You're calling System.loadLibrary() incorrect. 您正在调用System.loadLibrary()不正确。 The loadLibrary method takes a library name, eg "hello", and tries to load the corresponding shared object. loadLibrary方法采用库名称,例如“hello”,并尝试加载相应的共享对象。 On Unix, it will attempt to load "libhello.so", and on windows it will try to load "hello.dll". 在Unix上,它将尝试加载“libhello.so”,在Windows上它将尝试加载“hello.dll”。 It will expect the file to be found in java.library.path . 它期望在java.library.path找到该文件。

The method you probably intend to be calling is System.load() which takes a fully qualified filename and loads it. 您可能打算调用的方法是System.load() ,它接受一个完全限定的文件名并加载它。 This method should take a File as argument, but it takes a string instead. 此方法应将File作为参数,但它需要一个字符串。 If you use load , you'll have to handle local naming conventions manually, but you won't have to rely on java.library.path to be set. 如果使用load ,则必须手动处理本地命名约定,但不必依赖java.library.path进行设置。

Do the following: 请执行下列操作:

  1. change your Java class to this: 将您的Java类更改为:

     class Hello { public native void sayHello(); static { System.loadLibrary("hello"); } public static void main(String[] args) { Hello h = new Hello(); h.sayHello(); } } 
  2. rename hello.so to libhello.so: cp hello.so libhello.so or mv hello.so libhello.so 将hello.so重命名为libhello.so:cp cp hello.so libhello.somv hello.so libhello.so

  3. run as: java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello 运行方式: java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello

And are you running it with something like: 你用以下的东西运行它吗?

java -Djava.library.path=/home/gavin/Work/workspace/JNI Hello

You'll need to make sure the shared object is in your library path. 您需要确保共享对象位于库路径中。

OS: CentOS6.5. 操作系统:CentOS6.5。 JNIHello.java: JNIHello.java:

public class JNIHello {
                static {
                                System.loadLibrary("JNIHello");
                }
                private native void sayHello();
                public static void main(String args[]) {
                                JNIHello jniHello = new JNIHello();
                                jniHello.sayHello();
                }
}

export java home: export JAVA_HOME=/usr/java/jdk1.7.0_67-cloudera/ export java home:export JAVA_HOME = / usr / java / jdk1.7.0_67-cloudera /

compile java class: 编译java类:

javac JNIHello.java

generate JNIHello.h: 生成JNIHello.h:

javah JNIHello

implement sayHello in JNIHello.c: 在JNIHello.c中实现sayHello:

#include <jni.h>
#include <stdio.h>
#include "JNIHello.h"
/*
 * Class:     JNIHello
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_JNIHello_sayHello
  (JNIEnv *env, jobject obj) {
        printf("Hello world!\n");
        return;
}

compile library: 编译库:

gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" JNIHello.c -fPIC -shared -o JNIHello.so

run JNIHello: 运行JNIHello:

java -Djava.library.path=/home/ldp/caffe/test/ JNIHello
Hello world!

lib name format ref: lib名称格式参考:

3.1.1. Shared Library Names

Every shared library has a special name called the ``soname''. 每个共享库都有一个名为``soname''的特殊名称。 The soname has the prefix 'lib' , the name of the library, the phrase '.so' , soname有前缀'lib' ,库的名称, 短语'.so'

ref link ref链接

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

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