简体   繁体   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);
}

parameter conversion process as follows.参数转换过程如下。

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

why does w1 != w2 ?为什么w1 != w2


All JNI methods accept both local and global references as arguments.所有 JNI 方法都接受本地和全局引用作为参数。 It's possible for references to the same object to have different values.对同一对象的引用可能具有不同的值。 For example, the return values from consecutive calls to NewGlobalRef on the same object may be different.例如,对同一对象连续调用 NewGlobalRef 的返回值可能不同。 To see if two references refer to the same object, you must use the IsSameObject function.要查看两个引用是否引用同一个对象,您必须使用 IsSameObject 函数。 Never compare references with == in native code.切勿在本机代码中将引用与 == 进行比较。

One consequence of this is that you must not assume object references are constant or unique in native code.这样做的一个后果是您不能假设对象引用在本机代码中是常量或唯一的。 The 32-bit value representing an object may be different from one invocation of a method to the next, and it's possible ?that two different objects could have the same 32-bit value on consecutive calls.表示对象的 32 位值可能因方法的一次调用而异,并且有可能两个不同的对象在连续调用时具有相同的 32 位值。 Do not use jobject values as keys.不要使用作业值作为键。

Because jobject window is a local reference .因为作业jobject window本地参考 If you want to compare two object references whether they point to the same object you have to use JNIEnv* and IsSameObject its member function如果要比较两个对象引用是否指向同一个对象,则必须使用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));
}

More 更多

I faced this problem not too far ago.不久前我遇到了这个问题。 jobject s passed to JNI functions can have different values even they point to same objects.传递给 JNI 函数的jobject可以具有不同的值,即使它们指向相同的对象。 It happens because JVM has some kind of local objects pool and every tick it clears all local objects to GC if they have no global references.发生这种情况是因为 JVM 有某种本地对象池,并且如果它们没有全局引用,则每次滴答都会将所有本地对象清除到 GC。 So if you want to store a pointer to jobject in your C++ code you have to create a global reference from a local one.所以如果你想在你的 C++ 代码中存储一个指向 jobject 的指针,你必须从本地引用创建一个全局引用。 And please don't forget to release it with env->DeleteGlobalRef once you've done with your object or your program will have memory leaks otherwise.并且请不要忘记在处理env->DeleteGlobalRef对象后使用env->DeleteGlobalRef释放它,否则您的程序将出现内存泄漏。

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

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