使用JNI在C中访问Java对象中的Java对象
我对JNI比较陌生,并且已经解决了使用JNI在Java对象中弄乱整数和数组的基础知识。 现在我正在尝试修改/访问Java对象中的Java对象。
我一直在互联网和Stack Overflow上搜索,还没有找到如何做到这一点。
这是一个例子。
在Java中:
public class ObjectOne { private byte[] buff; ... ... } public class ObjectTwo { private ObjectOne obj; ... ... }
在JNI中,如何通过ObjectTwo从ObjectOne访问“buff”? 我试过这样的事……
JNIEXPORT void JNICALL Java_accessBuffThroughObjectTwo(JNIEnv *env, jobject obj, jobject objectTwo) { jclass clazz; jclass bufferClazz; jobject bufferJObject; clazz = (*env)->GetObjectClass(env, objectTwo); fid = (*env)->GetFieldID(env, clazz, "obj", "Ljava/lang/Object;"); bufferJObject = (*env)->GetObjectField(env, javascsicommand, fid); bufferClazz = (*env)->GetObjectClass(env, bufferJObject); GetFieldID(env, bufferClazz, "buff", "[B"); }
对我做错的任何帮助?
在尝试代码时,您可以轻松添加一些这样的断言:
JNIEXPORT void JNICALL Java_accessBuffThroughObjectTwo(JNIEnv *env, jobject obj, jobject objectTwo) { jclass clazz; jclass bufferClazz; jobject bufferJObject; jfieldID fid; clazz = (*env)->GetObjectClass(env, objectTwo); assert(clazz != NULL); fid = (*env)->GetFieldID(env, clazz, "obj", "Ljava/lang/Object;"); assert(fid != NULL); bufferJObject = (*env)->GetObjectField(env, javascsicommand, fid); assert(bufferJObject != NULL); bufferClazz = (*env)->GetObjectClass(env, bufferJObject); assert(bufferClazz != NULL); fid = (*env)->GetFieldID(env, bufferClazz, "buff", "[B"); assert(fid != NULL); }
这样做,您将首先看到第一个fid
将为NULL。 这是因为ObjectTwo
类没有java.lang.Object
类型的任何字段。 您应该将行更改为这样(但添加正确的包而不是com/package
):
fid = (*env)->GetFieldID(env, clazz, "obj", "Lcom/package/ObjectOne;");
如果再次运行,您会发现fid不再为null,并且断言将通过。
正如其他人所说,我相信javascsicommand
应该是objectTwo
。
现在断言失败的下一个地方是bufferJObject
。 这是因为该字段存在但对象为NULL,如果您检查Java代码,您会注意到obj
字段从未实例化并且为null
。
将您的Java代码更改为以下内容:
public class ObjectTwo { private ObjectOne obj = new ObjectOne(); ... ... }
您现在将传递断言,甚至传递所有其他断言。
总结一下,您正在访问一个null
对象并尝试在其上调用reflection:
bufferClazz = (*env)->GetObjectClass(env, bufferJObject); <-- The bufferJObject was NULL