当前位置: 首页 > 面试题库 >

使用JNI在C中的Java对象中访问Java对象

包翔
2023-03-14
问题内容

我对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");
}

我做错了什么吗?


问题答案:

在尝试代码时,您可以轻松地html" target="_blank">添加一些断言,例如:

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对象并尝试在其上调用反射:

bufferClazz = (*env)->GetObjectClass(env, bufferJObject); <-- The bufferJObject was NULL


 类似资料:
  • 问题内容: 我有一个JNI方法来访问返回一个Integer对象的java方法。我不想返回原始的int类型,因为将修改此代码以处理通用对象。以下是我所拥有的。我无法获得所传递的Integer的值。C ++端的输出类似于 如何获取在C ++端传递的Integer对象的实际值? 请帮忙。 谢谢, -H GenericPeer.cpp GenericPeer.java 资料库 Test.java(主类)

  • 问题内容: 看一下这个例子: 如何从子对象中访问随机对象? 问题答案: 让类将自己的实例传递给该类。 经典Occam剃刀。

  • 我有一组在工作中需要用C/C++运行的java类。 而且,由于我对java还很陌生,所以我要一步一步地走。我已经能够用string、int double等调用java,但最终的结果是返回一个字节数组(一个pdf文档),所以我尝试返回一个简单的两个元素的字节数组。 下面是Java:

  • 问题内容: 我正在浏览一个文档,遇到了一个称为的术语。我发现它是一个数据访问对象。有人可以解释一下这实际上是什么吗? 我知道这是一种用于从不同类型的源访问数据的接口,在我的这项小小的研究中,我碰到了一个称为数据源或数据源对象的概念,事情变得一团糟。 我真的很想知道a 的编程含义。如何使用?任何从最基本的东西解释这个概念的页面的链接也将受到赞赏。 问题答案: 数据访问对象基本上是一个对象或接口,可提

  • 我在浏览一个文档时遇到了一个叫做的术语。我发现它是一个数据访问对象。有人能解释一下这到底是什么吗?

  • 问题内容: 我已经搜索了很多,但找不到特定的解决方案。关于stackoverflow也有一些问题,但我无法找到满意的答案,所以我再次询问。 我在java中有一个如下类。 我知道如何在Java中使用线程。 现在我想同时执行这两个操作。为此,我创建了两个线程类,一个在运行中执行addString()逻辑,另一个在执行deleteString()逻辑中。我在每个线程的构造函数中传递mylist,但是在对