gpt4 book ai didi

java - JNI 调用失败并出现 UnsatisfiedLinkError

转载 作者:行者123 更新时间:2023-12-04 06:40:05 26 4
gpt4 key购买 nike

从 JNI 调用 C 函数时出现 UnsatisfiedLinkError,尽管我的设置似乎正确。这是我所做的:

有一个Java类:

package com.mycompany.myproduct;

public class Foo {
static {
System.loadLibrary("external");
}

public void native do_foo();
}

我已放置 libexternal.soLD_LIBRARY_PATH ,编译类,并执行 javah超过它。结果 com_mycompany_myproduct_Foo.h文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_mycompany_myproduct_Foo */

#ifndef _Included_com_mycompany_myproduct_Foo
#define _Included_com_mycompany_myproduct_Foo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_com_mycompany_myproduct_Foo
* Method: do_foo
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_mycompany_myproduct_Foo_do_1foo(JNIEnv *, jobject);

ctinative.c 中实现了 C 委派(不确定那里是否需要 extern "C"):
#include "com_mycompany_myproduct_Foo.h"

#include "External.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
* Class: com_com_mycompany_myproduct_Foo
* Method: do_foo
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_mycompany_myproduct_Foo_do_1foo(JNIEnv *, jobject) {
do_foo(); // this is a function that defined in External.h
}

#ifdef __cplusplus
}
#endif

编译得到 ctinative.o :
gcc -x c -g -m64 -DUNIX=1 -DUSE_SBUF=1 -DMAIN_VERSION=0 -DC_VER=7 -I$(EXTERNAL_SDK_ROOT)/include -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux -o ctinative.o -c ctinative.c

这是 nm ctinative.o 的输出(有 U有正常吗?):
0000000000000000 T Java_com_mycompany_myproduct_Foo_do_1foo
U do_foo

放置 ctinative.oLD_LIBRARY_PATH .现在调用 Foo.do_foo()我收到 UnsatisfiedLinkError:
java.lang.UnsatisfiedLinkError: com.mycompany.myproduct.Foo.do_foo()V
at com.mycompany.myproduct.Foo.do_foo(Native Method)

如果我删除 ctinative.o来自 LD_LIBRARY_PATH错误不会改变。如果我删除 libexternal.so来自 LD_LIBRARY_PATH那么我当然会得到:
java.lang.UnsatisfiedLinkError: no external in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at com.mycompany.myproduct.Foo.<clinit>

知道我做错了什么吗?

最佳答案

好的,我在 Linux 上使用 native 库的经验仅限于玩具测试,但是我在 Windows 上已经非常广泛地使用它们。我希望机制是相似的,但请谨慎行事:)

Java 最终调用 Java_com_mycompany_myproduct_Foo_do_1foo()执行方法时的原生函数fooInstance.do_foo() .这是需要在 libexternal.so 中定义的原生函数(或您选择使用 loadLibrary() 加载的任何内容)。

如果我正确理解您的问题,您已经编译了函数 Java_com_mycompany_myproduct_Foo_do_1foo()进入 ctinative.o , 并且实现没有出现在 libexternal.so .您可以通过 objdump --dynamic-reloc libexternal.so 进行检查.

我相信您需要拥有 Java_com_mycompany_myproduct_Foo_do_1foo() 的本地实现编译成libexternal.so ,或者您也可以链接 ctinative.o生成类似于 libctinative.so 的动态链接库.

编辑:要加入点,完整的机制将是:

  • 你的java代码调用loadLibrary().so实现函数Java_com_mycompany_myproduct_Foo_do_1foo()的文件.我们称之为 libctinative.so .
  • libctinative.so动态加载 libexternal.so通过 O/S 的动态链接机制 --- 除了编译和链接 libctinative.so 之外,您不需要做任何特别的事情来实现这一点以正确的方式
  • 假设没有其他问题,您的程序可以正常运行:)
  • 关于java - JNI 调用失败并出现 UnsatisfiedLinkError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4365955/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com