java - 如何在 JNI 调用之间保存对象?

标签 java android android-ndk java-native-interface

我有一个带有 native 代码的 Android 应用程序。如何在调用 native 方法之间保留对对象的引用?

// 1: create native object and hold it
Object obj = jni_wrapper.native_getObject();

// ... do smth

// 2: return an object back to native code
Object result = jni_wrapper.native_doSmthWithObject(obj);

因此,代码应该保存对对象的引用并以某种方式找到它(在上例中的 1: 和 2: 之间)。我可以创建自己的类和特殊实例字段(如果需要)来保存引用。

我使用了下一个解决方案(仅在索引对象的“指针”实例字段中保存指向实例的指针),但它似乎不起作用。

Java(索引.java):

/**
 *  CXIndex
 */
public class Index {

    private long pointer;

    public long getPointer() {
        return pointer;
    }
}

native 代码:

// index
static jclass IndexClass;
static jmethodID IndexConstructor;
static jfieldID IndexPointerField;

void bindIndex(JNIEnv *env)
{
    IndexClass = env->FindClass("name/antonsmirnov/xxx/dto/Index");
    IndexConstructor = env->GetMethodID(IndexClass, "<init>", "()V");
    IndexPointerField = env->GetFieldID(IndexClass, "pointer", "J");
}

// map CXIndex
jobject mapIndex(JNIEnv *env, CXIndex *index)
{
    if (IndexClass == NULL)
        bindIndex(env);


    jobject obj = env->NewObject(IndexClass, IndexConstructor);
    jlong jpointer = reinterpret_cast<jlong>(index);

    env->SetLongField(obj, IndexPointerField, jpointer);
    return obj;
}

// map Index -> CXIndex
CXIndex unmapIndex(JNIEnv *env, jobject jindex)
{
    if (IndexClass == NULL)
        bindIndex(env);

    jlong jpointer = env->GetLongField(jindex, IndexPointerField);
    CXIndex *ptr = reinterpret_cast<CXIndex*>(jpointer);
    return *ptr;
}

这与 Android 相关,它可以带来特定的行为!

最佳答案

这里至少有两个问题。

  1. 您无法保存对 jobjectjclass 的静态引用。您需要 GlobalRefWeakGlobalRef 来执行此操作。
  2. 您的 JNI 代码中完全没有错误检查。 GetClass()GetMethodID()GetFieldID()GetLongField()等的结果,必须全部检查并检查待处理的异常。

但是我不明白你为什么需要这个。您的第一个解决方案要容易得多,并且可以通过将私有(private) native 方法包装在公共(public) Java 方法中来隐形地实现,这些方法调用它们并自动提供所需的对象,其中该对象可以存储在具有 native 方法的类中。

关于java - 如何在 JNI 调用之间保存对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19183849/

相关文章:

java - 如何使用 k() 函数在 kdb/q 中接收数据

java - 如何递归列出目录中的所有 .rar 文件

Android sqlite 数据库 - 我从哪里开始,因为记事本教程已经消失了?

android - FFMPEG android编译错误

android - 使用没有 jni 文件夹的 ndk-build 构建 android 共享库

java - Spring Boot :org. springframework.beans.factory.UnsatisfiedDependencyException

java - edittext 中的输入文本恢复为可扩展 ListView 中的预设文本

android - 屏幕旋转后如何恢复textview滚动位置?

android - 即使没有更改,ndk-build 也会安装库。这可以改变吗?

java - 尝试在 Android 应用程序(java)上设置静音按钮