繁体   English   中英

通过 jni 将相同的 Android Surfaceview 传递给 C++ 代码会导致不同的值

[英]Passing the same Android surfaceview to C++ code via jni results in different values

//Android
SurfaceView SW;

function doSomthing()
{
    startPreview(SW);
    snapShot(SW);
}

//C++
startPreview(jobject window)
{
    TDebug("w1 = %u",window);
}

snapshot(jobject window)
{
    TDebug("w2 = %u",window);
}

参数转换过程如下。

SurfaceView ->Object->Jobject(jni)->void*(C++)

为什么w1 != w2


所有 JNI 方法都接受本地和全局引用作为参数。 对同一对象的引用可能具有不同的值。 例如,对同一对象连续调用 NewGlobalRef 的返回值可能不同。 要查看两个引用是否引用同一个对象,您必须使用 IsSameObject 函数。 切勿在本机代码中将引用与 == 进行比较。

这样做的一个后果是您不能假设对象引用在本机代码中是常量或唯一的。 表示对象的 32 位值可能因方法的一次调用而异,并且有可能两个不同的对象在连续调用时具有相同的 32 位值。 不要使用作业值作为键。

因为作业jobject window本地参考 如果要比较两个对象引用是否指向同一个对象,则必须使用JNIEnv*IsSameObject其成员函数

static jobject window1=nullptr;
static jobject window2=nullptr;

Java_your_prefix_class_startPreview(JNIEnv *env,jobject thiz,jobject window){
    window1=env->NewGlobalRef(window);
}

Java_your_prefix_class_snapshot(JNIEnv *env,jobject thiz,jobject window){
    window2=env->NewGlobalRef(window);

    TDebug("windows are equal = %d", env->IsSameObject(window1, window2));
}

更多

不久前我遇到了这个问题。 传递给 JNI 函数的jobject可以具有不同的值,即使它们指向相同的对象。 发生这种情况是因为 JVM 有某种本地对象池,并且如果它们没有全局引用,则每次滴答都会将所有本地对象清除到 GC。 所以如果你想在你的 C++ 代码中存储一个指向 jobject 的指针,你必须从本地引用创建一个全局引用。 并且请不要忘记在处理env->DeleteGlobalRef对象后使用env->DeleteGlobalRef释放它,否则您的程序将出现内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM