【问题标题】:java.lang.UnsatisfiedLinkError when using JNI on ubuntu在 ubuntu 上使用 JNI 时出现 java.lang.UnsatisfiedLinkError
【发布时间】:2015-05-07 13:12:47
【问题描述】:

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

拿起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)
make: *** [运行] 错误 1

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

【问题讨论】:

  • 您能否也粘贴您的本机文件HelloJNI.c?这将使人们更容易重现这一点。
  • 您需要-Djava.library.path 才能真正包含包含libHelloJNI.so 的目录。
  • #include #include #include "HelloJNI.h" JNIEXPORT void JNICALL Java_HelloJNI_sayHello (JNIEnv * env, jobject thisObj) { printf("Hello Momo. 这是C 代码。");返回; }
  • 询问有关使用本网站的非技术问题。我可以编辑我的问题吗?
  • 是的,您可以编辑您的问题。您的问题下方有一个灰色的“编辑”文本。每个人都可以编辑您的问题。这就是 StackOverflow 的设计目的。

标签: java java-native-interface


【解决方案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)

【讨论】:

  • 非常感谢 Christian 的帮助:) 我认为失败的原因是 linux 上的 'lib' 前缀
  • 是的 :) 如果您认为它是正确的,请不要忘记接受答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-04
  • 2014-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 2015-02-05
相关资源
最近更新 更多