使用JNI时的java.lang.UnsatisfiedLinkError。
我的测试环境:
Ubuntu 12.04 / 64-bit
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应用程序时,会出现OLD问题:
选择JAVA_TOOL_OPTIONS:-Dfile.encoding = UTF8 的java.library.path =:/家庭/ mancook /厨师/工作/ StSoftware / src目录/ JAVA / StTestJni / tutor01_HelloJNI:在/ usr / JAVA /包装/ lib中/ AMD64:在/ usr / lib64下:/ lib64目录:/ lib目录:/ usr / lib
线程“main”中的异常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)
make:*** [运行]错误1
我已针对此问题使用Google搜索,发现这是一个旧问题。但我不能找到解决我问题的方法!!希望可以有人帮帮我。 提前致谢。
答案 0 :(得分:1)
Makefile中需要-Djava.library.path=.
,您需要使用 System.loadLibrary("HelloJNI");
- 没有lib
前缀,没有.so
后缀来加载库。前缀和后缀由Java处理 - 想想看,Windows上的命名方案是不同的(愚蠢但事实)。并且要注意在代码中System.loadLibrary()
两次陷阱的缺陷,如果只更改其中一个,它仍然会失败。那个实际上花了我几分钟:P
P.S。:我建议您对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)