【问题标题】:JNI Use native methodJNI 使用本机方法
【发布时间】:2014-04-04 09:11:23
【问题描述】:

我正在做一个需要从 dll 文件中调用一些方法的项目。 这两个dll是

  • EasySign.dll
  • EasySignJNI

EasySignJNI 依赖于 EasySign。

我编写了加载 EasySignJNI 的类,如下所示:

package easysign;


class EasySign {

    EasySign(){}

    public native String EasyHashFile(String filename);
    public native int EasySign(String pkcs11_driver,String pin, int type, String file_data, int out_format, String signed_file, String cert_out, int cert_format);
    public native int EasyVerify(String cert_user, String file_data, String signed_file, String crl_file, String ca_file, String out_document);


    static {
        System.loadLibrary("EasySignJNI");
    }
 }

现在我会像这样从我的主要方法中调用这些方法:

public class Test {
   public static void main(String[] args) throws IOException{
          EasySign es = new EasySign();
          System.out.println("EasyHashFile : " + es.EasyHashFile("test.txt"));
        }
    }

我必须在 -Djava.library.path 中指定什么?只有我的 EasySignJNI.dll 所在的路径?这样可以调用native方法吗? 为了完整性,我使用 NetBeans。

编辑: 我注意到提供给我的第三方 dll(特别是 JNI dll)定义了没有任何包的方法名称,因此我不得不将加载 dll 的类放在默认包中。有没有办法只更改 dll 方法名称,包括我自己的包名称?

编辑 2: 我的意思是 EasySign.dll 和 EasySignJNI.dll 都是按原样提供给我的,我无法修改它们(我没有源代码)。 EasySignJNI 是 JNI 部分,但检查它我注意到方法符号的格式为:_java_EasySign_MethodName。当我从我的 Easysign 类加载 Java 中的 dll 时(这个类必须驻留在“mypackage”包中),我收到 jni unsatisfiedlinkerror 因为,如果我理解正确,我正在调用“_java_mypackage_EasySign_MethodName”方法,即标志是不同于dll的。那么让它工作的唯一方法是重写JNI部分并构建它以具有JNI方法的正确符号?

【问题讨论】:

    标签: java dll methods java-native-interface


    【解决方案1】:

    我必须在 -Djava.library.path 中指定什么?只有我的 EasySignJNI.dll 所在的路径?

    正确,只要依赖的 EasySign.dll 在操作系统期望的位置可用,操作系统就会为您找到它。

    这种方式可以调用native方法吗?为了完整性,我使用 NetBeans。

    我阅读了你的编辑,你成功地失去了我。你指的是什么默认包? (请记住,我们都不知道 EasySign.dll 是什么)所以,我将提供一些关于我如何执行您最初描述的操作的信息,希望对您有所帮助。

    如果你有源代码,首先编译 EasySign。不要构建 DLL 或共享对象,而是构建静态库。如果您没有 EasySign 的 src 代码或预构建的静态库,您将被 dll 卡住,可以继续下一步。

    现在您已准备好编译 jni 部分。您的所有 JNI C 代码基本上都应该将您的 Java 输入/输出转换为它们的 JVM/Native 类型,并调用 DLL 库中的适当函数。您希望保持该层尽可能薄且简单,因为调试起来非常困难。您的 C++ 包名称在这里并不重要,您可以为 Java 类使用您想要的任何包名称。您应该能够编译 JNI 代码,最好是静态链接到 EasySign.dll 文件,这样您就不必担心分发它。如果必须动态链接,请确保将 EasySign.dll 安装到 DLL PATH / LDPATH 上的位置,因为操作系统需要在 JVM 加载 JNI DLL 后立即定位并加载该文件。

    此时,您应该能够将 -Djava.library.path 指向您的 JNI DLL 的路径,并且一切正常。

    【讨论】:

    • 感谢您的回复,对不清楚的地方深表歉意!我已编辑问题以使其更清楚!
    • 感谢您的更新!这确实澄清了很多!如果向您提供了 EasySignJNI,他们还必须为您提供包含他们用于构建 JNI 库的本机方法声明的 JAR。不幸的是,编译库后您无法修改本机方法签名。所以回答你的问题;是的,您必须重新编译 JNI 部分才能更改包名称。
    猜你喜欢
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多