li hu li hu - 7 months ago 46
Java Question

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

SurfaceView SW;

function doSomthing()

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

All JNI methods accept both local and global references as arguments. 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. To see if two references refer to the same object, you must use the IsSameObject function. 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. Do not use jobject values as keys.


Because jobject window is a local reference. 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

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

Java_your_prefix_class_startPreview(JNIEnv *env,jobject thiz,jobject window){

Java_your_prefix_class_snapshot(JNIEnv *env,jobject thiz,jobject window){

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


I faced this problem not too far ago. jobjects passed to JNI functions can have different values even they point to the same objects. 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. 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. 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.