无法从C代码对Java getter进行JNI调用

时间:2017-06-24 16:52:12

标签: java c java-native-interface

我可以成功地对java进行JNI调用。我从JNI调用中获取一个数组。但我无法访问此数组中的元素。

以下是我的C代码:

void jniInvokeMethod(JNIEnv* env, jclass cls, jobject object) {
    jstring folderName = (*env)->NewStringUTF(env, "");
    jstring token = (*env)->NewStringUTF(env, "Second string");

    jmethodID getFolderContents = (*env)->GetMethodID(env, cls, "getFolderContents", "(Ljava/lang/String;Ljava/lang/String;)[Lcom/labsite/rest/model/FolderOrFile;");
    if (getFolderContents != 0) {
        printf("getFolderContents found\n");
    }

    jobjectArray folderContents = (*env)->CallObjectMethod(env, object, getFolderContents, folderName, token);
    printf("%s\n", folderContents);

    jobject* elem = (*env)->GetObjectArrayElement(env, folderContents, 0);
    for (int i = 0; i < (*env)->GetArrayLength(env, folderContents); i++) {
        jobject folderContentObj = elem[i];
        //jclass cls = (*env)->GetObjectClass(env, folderContentObj);
        jclass folderOrFileCls = (*env)->FindClass(env, "Lcom/labsite/rest/model/FolderOrFile;");
        jmethodID getSizeMethod = (*env)->GetMethodID(env, folderOrFileCls, "getSize", "()J");
        (*env)->CallObjectMethod(env, folderContentObj, getSizeMethod);
    }
}

以下是我从C调用的方法:

public class Client {
  public FolderOrFile[] getFolderContents(String folderName, String token) {
  ...
  }
}

Visual Studio Debugger在执行(*env)->CallObjectMethod(env, folderContentObj, getSizeMethod)行时停止,提供以下错误消息:

  

在mirror.exe中的0x0000000058A498ED(jvm.dll)抛出异常:   0xC0000005:访问冲突读取位置0x0000000000000009。

以下是返回的课程:

public class FolderOrFile implements Serializable {
  ...
  private long size;

  public long getSize() { return size;}
  ....
}

我可以调用getFolderContents()方法。但我不能调用一个物体的吸气剂。 getSize()调用有什么问题? (同样的事情适用于FolderOrFile类的其他方法。

我应该如何解释Visual Studio提供的错误消息?

1 个答案:

答案 0 :(得分:3)

你在这里弄错了:

jobject* elem = (*env)->GetObjectArrayElement(env, folderContents, 0);

GetObjectArrayElement会返回jobject,而非jobject*。由于jobject对于不同的指针类型是typedef,因此代码仍会编译(带有警告,所以如果没有,请务必将其打开!)。然后,当您尝试索引此指针时:

jobject folderContentObj = elem[i];

您实际上获得了jobject的或多或少的随机值(无论在内存中发生了什么),因此当您尝试将其与CallObjectMethod一起使用时,您将获得访问冲突。< / p>

对象数组没有等效的Get<PrimitiveType>ArrayElements(我的猜测是,这是因为VM内部的内存布局存在差异)。因此,访问元素的方法是在每次迭代时调用GetObjectArrayElement

jobject folderContentObj = (*env)->GetObjectArrayElement(env, folderContents, i);