我可以成功地对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提供的错误消息?
答案 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);