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

时间:2015-03-06 00:05:47

标签: java java-native-interface

使用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搜索,发现这是一个旧问题。但我不能找到解决我问题的方法!!希望可以有人帮帮我。 提前致谢

1 个答案:

答案 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)