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

我想在Ubuntu 8.10上使用JNI,使用Eclipse和gcc(如果有风味,则使用Ubuntu的标准版)。

尽管make文件成功创建,我似乎无法加载我的库。

主要的Java类如下:

class Hello { public native void sayHello(); static { System.loadLibrary("hello.so"); } public static void main(String[] args) { Hello h = new Hello(); h.sayHello(); } } 

我的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 

其余的代码(Hello.c)看起来像人们想的那样。

我得到的错误如下;

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

如果我使用显式路径:

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

然后它可以工作,但如果可能的话,我宁愿不使用显式路径。

根据Pax,您应该将库路径设置为Java应该查找库的位置。 您的库名应该是libhello.so。 然后,加载库的调用应该是:

 System.loadLibrary("hello"); 

Linux库由约定lib 名称 .so引用,并根据名称加载。 以下是SWIG文档中关于Java中动态链接问题的链接 ,尽管您未使用SWIG,但此部分仍然具有相关性。

您正在调用System.loadLibrary()不正确。 loadLibrary方法采用库名称,例如“hello”,并尝试加载相应的共享对象。 在Unix上,它将尝试加载“libhello.so”,在Windows上它将尝试加载“hello.dll”。 它期望在java.library.path找到该文件。

您可能打算调用的方法是System.load() ,它接受一个完全限定的文件名并加载它。 此方法应将File作为参数,但它需要一个字符串。 如果使用load ,则必须手动处理本地命名约定,但不必依赖java.library.path进行设置。

请执行下列操作:

  1. 将您的Java类更改为:

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

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

你运行它是这样的:

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

您需要确保共享对象位于库路径中。

操作系统:CentOS6.5。 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 /

编译java类:

 javac JNIHello.java 

生成JNIHello.h:

 javah JNIHello 

在JNIHello.c中实现sayHello:

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

编译库:

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

运行JNIHello:

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

lib名称格式参考:

 3.1.1. Shared Library Names 

每个共享库都有一个名为“soname”的特殊名称。 soname有前缀’lib’ ,库的名称, 短语’.so’

ref链接