Java JNI GetMethodID 返回 NULL。

4

我有一个Java类:

public class CameraActivity extends Activity {

  ...      

  public class RecognitionResult {
    public String text;
    public int x;
    public int y;
    public int width;
    public int height;

    public RecognitionResult(String text, int x, int y, int width, int height) {
      this.text = text;
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
    }
  }
}

这是我的JNI代码:

extern "C"
jobject Java_com_example_parkingcontrolsystem_CameraActivity_recognizeNumberPlate(JNIEnv *env,
                                                                                  jobject object,
                                                                                  jstring filename)
{
  jclass cls = env->FindClass("com/example/parkingcontrolsystem/CameraActivity$RecognitionResult");
  std::cout << "Class: " << cls << std::endl;

  jmethodID constructor = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;IIII)V");
  std::cout << "Method: " << constructor << std::endl;

  recognition_result = env->NewObject(cls, constructor, "Hello from JNI", 0, 0, 50, 100);
  std::cout << "Object: " << recognition_result << std::endl;

  return recognition_result;
}

FindClass返回的不是NULL,很好。但是GetMethodID总是返回0。我尝试创建一个没有参数的默认构造函数,然后使用“()V”签名,但是GetMethodID返回NULL。

出了什么问题?


4
"(Lcom/example/parkingcontrolsystem/CameraActivity;Ljava/lang/String;IIII)V" 表示一个 Java 方法的签名,其中括号内的部分表示方法参数,分别为类型为 CameraActivity 的对象、类型为 String 的对象和四个整数。而 V 则表示该方法没有返回值。这是用 Java 虚拟机 (JVM) 中的字节码来描述方法的方式。 - Selvin
2
只剩下两分钱:下一个问题是,您无法在没有“CameraActivity”实例的情况下调用此构造函数(但我不确定是否可以在JNI中执行此操作)...因此最好将其设置为静态内部类或根本不是内部类。 - Selvin
谢谢,伙计!方法已找到!好的,我将把这个类作为静态内部类。 - herolover
1
2Selvin:请将其作为答案,这样原帖的作者可以接受,并且后代也能从中受益。 - Seva Alekseyev
1个回答

4
如果使用JNI实例化内部类,则需要在与GetMethodId一起使用的签名中传递父对象,以便接收有效的jmethodID
假设BA的内部类,具有以下构造函数:public B(int someint),则以下代码将起作用(jobj指向A的实例):
jclass jclazz = env->FindClass("org/somepackage/A$B");
assert(jclazz != nullptr);
jmethodID mid = env->GetMethodID(jclazz, "<init>", "(Lorg/somepackage/A;I)V");
assert(mid != nullptr);
env->NewObject(jclazz, mid, jobj, 1);

一种解决运维问题的方法是:
 jclass cls = env->FindClass("com/example/parkingcontrolsystem/CameraActivity$RecognitionResult");
 std::cout << "Class: " << cls << std::endl;
 jmethodID constructor = env->GetMethodID(cls, "<init>","Lcom/example/parkingcontrolsystem/CameraActivity;Ljava/lang/String;IIII)V");
 std::cout << "Method: " << constructor << std::endl;
 recognition_result = env->NewObject(cls, constructor, object, "Hello from JNI", 0, 0, 50, 100);
 std::cout << "Object: " << recognition_result << std::endl;

注意:感谢Selven在评论区中发布了相同的答案,但没有发布答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接