5

我对 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);  <-- Fails here for Access Violation
    fid = (*env)->GetFieldID(env, bufferClazz, "buff", "[B");
}

对我做错了什么有帮助吗?

4

1 回答 1

15

在尝试您的代码时,您可以轻松添加一些断言,如下所示:

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.

现在断言将失败的下一个地方是 on bufferJObject。这是因为该字段存在但对象为 NULL,如果您检查您的 java 代码,您会注意到该obj字段从未实例化并且是null.

将您的 java 代码更改为以下内容:

public class ObjectTwo
{
    private ObjectOne obj = new ObjectOne();
    ...
    ...
}

您现在将传递断言,甚至传递所有其他断言。

总而言之,您正在访问一个null对象并尝试对其调用反射:

bufferClazz = (*env)->GetObjectClass(env, bufferJObject); <-- The bufferJObject was NULL
于 2012-08-06T08:57:02.043 回答