java.lang.UnsatisfiedLinkError 在 ubuntu 上使用 JNI 时

java.lang.UnsatisfiedLinkError when using JNI on ubuntu

java.lang.UnsatisfiedLinkError 使用 JNI 时。

我的测试环境:

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 应用程序时,出现老问题:

Picked up 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
Exception in thread "main" java.lang.UnsatisfiedLinkError: no libHelloJNI in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
at HelloJNI.main(HelloJNI.java:22)
make: *** [run] Error 1

我在互联网上搜索了这个问题,发现这是一个老问题。但是我无法找到任何方法来解决我的问题!!希望可以有人帮帮我。 提前致谢

Makefile中需要-Djava.library.path=.,加载库时需要System.loadLibrary("HelloJNI");——没有lib前缀,没有.so后缀。前缀和后缀由 Java 处理 - 想一想,Windows 上的命名方案是不同的(愚蠢但事实)。并且要注意你的代码中有两次 System.loadLibrary() 的陷阱,如果你只更改其中一个,它仍然会失败。那个实际上花了我几分钟时间 :P

P.S.: 我建议对您的 Makefile 进行一些更改。我会使用 $(RM) 而不是 rm。不是文件的目标应该声明 .PHONY。不涉及自动变量的变量可以用 := 代替 = 赋值。我将使用单独的步骤从 .o 文件创建 .so。我会使用模式规则来编译 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)