JNI / JNA不满意链接,但符号存在

时间:2018-03-20 14:54:55

标签: java java-native-interface jna

我正在尝试通过提供的c-library“libext.so”集成遗留系统。 为了测试JNA / JNI,我想调用“setProperty”函数。

objdump libext.so -t | grep setProperty
0000000000104d50 g   F .text  000000000000000e Java_ExtClass_setProperty
0000000000104be0 g   F .text  000000000000016a Java_com_company_ExtClass_setProperty

这是我的代码,使用java 8,jna 4.5.1和/或native jni,在调用函数时两种方式都失败了UnsatisfiedLinkError - 加载库没有异常。

public class TestClass
{
    static {
        try {
            System.load("/path/to/libext.so");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
                Native.loadLibrary(("/path/to/libext.so"), CLibrary.class);
        void setProperty(String key, String value);
    }

    public static native synchronized void setProperty(String key, String value);

    public static void main(String[] args) {
        // setProperty("a", "b");
        CLibrary.INSTANCE.setProperty("a", "b");
    }
}

我错过了什么?

@Update:

我现在将JNI类和JNA INterface都移动到正确的包并重命名为jna接口

package com.company;

 public interface LibExtLibrary extends Library {
    LibExtLibrary INSTANCE = (LibExtLibrary)
            Native.loadLibrary(("/path/to/libext.so"),
                    LibExtLibrary.class);

    void Java_com_company_ExtClass_setProperty(String key, String value);
    void Java_ExtClass_setProperty(String key, String value);
    void ExtClass_setProperty(String key, String value);
    void setProperty(String key, String value);
}

在INSTANCE上调用前两个方法会产生InvalidMemoryAccess,后两个方法会产生UnsatisfiedLinkError

只要完全限定的类名等于本机库中定义的类名,JNI方法就可以工作

1 个答案:

答案 0 :(得分:1)

如果问题是"为什么我不能用JNA调用JNI方法?":

为了能够从Java调用外部库,您必须使用JNI。您将某些方法声明为nativejavah将为您生成可以填写代码的特殊函数。每个函数都有两个额外的参数:绑定到调用Java线程的env指针和作为方法接收器的对象或类。如果您将Java对象作为其他参数之一传递,您将在函数中获得jobject

如果JNI函数的实现只包括将调用转发到另一个外部库,您也可以使用JNA。 JNA 使用 JNI来包装libffi,以便您可以直接调用现有的外部库。这样您就不必自己创建包装库。 JNA不会创建env指针或将方法接收器作为参数传递。它会尝试将所有其他参数整理成外部库理解的东西。这意味着此处没有jobject

总结:JNI调用为其显式创建的函数,参数是Java特定的。 JNA在内部使用JNI来调用非Java外部库中的函数。