【问题标题】:Call Java from C using JNI使用 JNI 从 C 调用 Java
【发布时间】:2019-04-09 05:04:07
【问题描述】:

我正在尝试使用以下代码从 C 代码中调用 Java 函数 performSHA()。但我不断收到错误消息,提示“在非结构或联合的情况下请求成员‘DestroyJavaVM’”。我已经在线检查了几个链接,似乎我正在使用它。

JavaVM *jvm;       
JNIEnv *env;      
JavaVMOption options[3];
JavaVMInitArgs vm_args; 
vm_args.version  = JNI_VERSION_1_2;

JNI_GetDefaultJavaVMInitArgs(&vm_args);
options[0].optionString = "/home/amy/jni/";
vm_args.options  = options;

JNI_CreateJavaVM(&jvm, &env, &vm_args);
jclass cls = (*env)->FindClass(env, "CallToBCLib");
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "performSHA", "ILjava/lang/String;");
(*env)->CallStaticVoidMethod(cls, mid, algo_id, tc->m1);
jvm->DestroyJavaVM();   <-- ERROR

FindClass、GetStaticMethodID 和 CallStaticVoidMethod 的用法也正确吗? performSHA 是我正在调用的 Java 函数,而 algo_id, tc->m1 是我对 Java 函数的参数...

【问题讨论】:

  • github.com/clibs/sha1 稍后谢谢。
  • 这与 DestroyJavaVM 的问题无关,但您正在取消引用 env 即使它已经是一个指针。之后,您尝试使用 -> 运算符访问其成员,即使您拥有的不是 JNIEnv * 而是 JNIEnv。
  • @Daniel: (*env)-&gt; 很好,简单来说就是你在 C 中的做法。JNIEnv 本身就是一个指针。
  • @Michael 啊,我没有看到指针在 typedef 中...为什么人们在 C 中使用的代码中的 typedef 中隐藏星号:\

标签: java c java-native-interface


【解决方案1】:

我通过以下方式解决了这个问题:

(*jvm)->DestroyJavaVM(jvm);

【讨论】:

    【解决方案2】:

    根据documentation,您应该向DestroyJavaVM函数提供JavaVM *vm类型的参数:

    jint DestroyJavaVM(JavaVM *vm);
    

    因此,将jvm-&gt;DestroyJavaVM() 替换为DestroyJavaVM(jvm)

    请注意,在同一页面上,有一个“概述”示例,其中 DestroyJavaVM() 在您的代码 (jvm-&gt;DestroyJavaVM()) 中被调用,但这适用于 C++,并且您提到您正在尝试从 C 调用 Java 代码.

    【讨论】:

    • 我试过 jvm->DestroyJavaVM(&jvm) 和 DestroyJavaVM(&jvm) 但似乎都不起作用。陈述有什么问题吗? DestroyJavaVM(&jvm) 给出未定义的引用错误。第一个选项给出了与上面帖子中提到的相同的错误......
    • 你应该按照以下方式使用它DestroyJavaVM(jvm)(更新了我的答案)。
    • DestroyJavaVM(jvm) 这给出了未定义的引用错误。 “JNI_GetDefaultJavaVMInitArgs”、“JNI_CreateJavaVM”和“DestroyJavaVM”给出未定义的引用错误...
    • 那么 make 命令究竟做了什么?如果没有这些细节,恐怕我无法为您提供帮助。
    • link 这是我运行“make”命令时使用的make文件...
    【解决方案3】:

    这有点太长了,无法发表评论,所以我会把它作为答案。 我在 jni 源代码中检查了您应该如何访问 DestroyJavaVM
    该函数定义为here,这是声明:

    jint JNICALL jni_DestroyJavaVM(JavaVM *vm)
    

    bottom of that page 是 C 源代码中使用的函数调用表。

    规范给了我们JavaVM类型here的定义。
    我们可以看到JavaVM类型的定义就是函数调用表本身。

    这意味着我们需要获取 jvm 变量并访问其 DestroyJavaVM 函数,
    同时还传递了 jvm 实例本身,因此访问代码应如下所示:

    jvm->DestroyJavaVM(jvm);
    

    我还没有测试过,这样调用函数有点奇怪,但我猜这应该可以工作。

    【讨论】:

      猜你喜欢
      • 2012-03-28
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-04
      • 1970-01-01
      相关资源
      最近更新 更多