使用JNI时出现java.lang.UnsatisfiedLinkError。
我的测试环境:
Ubuntu 12.04 / 64位
JDK 1.7
gcc(Ubuntu / Linaro 4.6.3-1ubuntu5)
这是我的java来源:
public class HelloJNI {
static {
//System.loadLibrary("libHelloJNI");
}
private native void sayHello() ;
public static void main(String[] args){
//System.getProperties().list(System.out);
String lib_path = System.getProperty("java.library.path");
System.out.println("java.library.path=" + lib_path);
System.loadLibrary("libHelloJNI");
HelloJNI myJNI = new HelloJNI();
myJNI.sayHello();
}
}
这是我的C源代码:
#include <stdio.h>
#include "HelloJNI.h"
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj)
{
puts("Hello Momo. This is C code.");
return;
}
这是我的Makefile:
JNI_INC=-I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux"
JNI_LIB=libHelloJNI.so
JNI_OUT=$(JNI_LIB) HelloJNI.h HelloJNI.class
CFLAGS= $(JNI_INC) -fPIC -shared
all: $(JNI_OUT)
HelloJNI.h: HelloJNI.class
javah -jni HelloJNI
$(JNI_LIB): HelloJNI.c HelloJNI.h
gcc $(CFLAGS) -o $@ HelloJNI.c
HelloJNI.class: HelloJNI.java
javac HelloJNI.java
run:
java HelloJNI
#java -Djava.library.path=. HelloJNI
clean:
rm $(JNI_OUT)
当我运行Java应用程序时,会出现旧问题:
捡起JAVA_TOOL_OPTIONS:-Dfile.encoding = UTF8
java.library.path =。:/ home / mancook / cook / work / StSoftware / src / java / StTestJni / tutor01_HelloJNI:/ usr / java / packages / lib / amd64:/ usr / lib64:/ lib64:/ lib:/的usr / lib
线程“主”中的异常java.lang.UnsatisfiedLinkError:java.library.path中没有libHelloJNI
在java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
在java.lang.Runtime.loadLibrary0(Runtime.java:849)
在java.lang.System.loadLibrary(System.java:1088)
在HelloJNI.main(HelloJNI.java:22)
使:*** [运行]错误1
我已经用互联网搜索了这个问题,发现这是一个老问题。但是我找不到解决我问题的方法!希望可以有人帮帮我。提前致谢。
最佳答案
您需要在Makefile中使用-Djava.library.path=.
,并且需要使用System.loadLibrary("HelloJNI");
加载库-没有lib
前缀,没有.so
后缀。前缀和后缀由Java处理-考虑一下,Windows上的命名方案不同(愚蠢但事实)。并且要注意在代码中两次使用System.loadLibrary()
的陷阱,如果仅更改其中之一,它仍然会失败。那实际上花了我几分钟:P
附注:我建议您对Makefile进行一些更改。我会使用$(RM)
而不是rm
。不是文件的目标应声明为.PHONY
。可以使用:=
而不是=
分配不引用自动变量的变量。我将使用一个单独的步骤从.so
文件创建.o
。我将使用模式规则来编译Java,例如%.class: %.java
。我将使用模式规则来创建头文件,例如%.h: %.class
。 -I
的内容应该在CPPFLAGS
而不是CFLAGS
中,因为它用于预处理程序。然后-shared
应该进入LDFLAGS
,依此类推...
这是您的新Makefile
:
CPPFLAGS:=-I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux"
JNI_LIB:=libHelloJNI.so
JNI_OUT:=$(JNI_LIB) HelloJNI.o HelloJNI.h HelloJNI.class
CFLAGS:=-fPIC
LDFLAGS:=-shared
.PHONY: all
all: $(JNI_OUT)
%.h: %.class
javah -jni HelloJNI
$(JNI_LIB): HelloJNI.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
HelloJNI.o: HelloJNI.c HelloJNI.h
%.class: %.java
javac HelloJNI.java
.PHONY: run
run:
java -Djava.library.path=. HelloJNI
.PHONY: clean
clean:
$(RM) $(JNI_OUT)