使用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)

10-06 07:00
查看更多