JNI - GetObjectField返回NULL

Dan*_*oof 2 java java-native-interface android

我目前正在研究Mangler的 Android实现.

我有一个看起来像这样的java类:

public class VentriloEventData {
 public short type;
 public class _pcm {
  public int   length;
     public short  send_type;
     public int  rate;
     public byte  channels;
 };
 _pcm pcm;
}
Run Code Online (Sandbox Code Playgroud)

我的pcm对象的签名:

$ javap -s -p VentriloEventData
...
org.mangler.VentriloEventData$_pcm pcm;
  Signature: Lorg/mangler/VentriloEventData$_pcm;
Run Code Online (Sandbox Code Playgroud)

我正在实现一个名为getevent的本机JNI函数,它将写入VentriloEventData类实例中的字段.对于它的价值,它是用Java定义和调用的,如下所示:

public static native int getevent(VentriloEventData data);
VentriloEventData data = new VentriloEventData();
getevent(data);
Run Code Online (Sandbox Code Playgroud)

我的JNI实现了getevent:

JNIEXPORT jint JNICALL Java_org_mangler_VentriloInterface_getevent(JNIEnv* env, jobject obj, jobject eventdata) {
 v3_event *ev = v3_get_event(V3_BLOCK);
 if(ev != NULL) {
  jclass event_class = (*env)->GetObjectClass(env, eventdata);

  // Event type.
  jfieldID type_field = (*env)->GetFieldID(env, event_class, "type", "S");
  (*env)->SetShortField(
   env, 
   eventdata, 
   type_field, 
   1234
  );

  // Get PCM class.
  jfieldID pcm_field = (*env)->GetFieldID(env, event_class, "pcm", "Lorg/mangler/VentriloEventData$_pcm;");
  jobject pcm = 
  (*env)->GetObjectField(
   env, 
   eventdata, 
   pcm_field
  );
  jclass pcm_class = (*env)->GetObjectClass(env, pcm);

  // Set PCM fields.
  jfieldID pcm_length_field = (*env)->GetFieldID(env, pcm_class, "length", "I");
  (*env)->SetIntField(
   env,
   pcm,
   pcm_length_field,
   1337
  );

  free(ev);
 }
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码适用于写入类型字段(不包含在_pcm类中).调用getevent后,在java端验证data.type为1234 :)

我的问题是断言"pcm!= NULL"将失败.请注意,pcm_field!= NULL,这可能表示该字段的签名是正确的......所以我对GetObjectField的调用肯定有问题.如果我将它与官方JNI文档进行比较,它看起来很好.

在过去的2个小时里,我一直在抨击这个问题而且我有点绝望了......希望不同的观点可以帮助我解决这个问题.

edit1:这不适用于任何嵌套对象,即使是简单的'Ljava/lang/String;' 将失败.
edit2:ExceptionOccurred和ExceptionCheck都返回JNI_FALSE.
edit3:也不适用于静态字段.

Dav*_*ter 6

好吧,如果这是完整的代码,那么我想pcm 应该是NULL.该对象pcm永远不会在Java端或C++端实例化.