1

In Android JAVA code:

public native int addRenderer(int channel, Object glSurface);

Context context = getApplicationContext();
SurfaceView svRemotePartyA = new SurfaceView(context);
SurfaceView svRemotePartyB = new SurfaceView(context);

addRenderer(0, svRemotePartyA);
addRenderer(1, svRemotePartyB);

In Android JNI C++ code:

extern "C" jint JNIEXPORT JNICALL Java_addRenderer(
    JNIEnv* jni, 
    jobject j_vie, 
    jint channel,
    jobject surface) {

    LOG(LS_INFO) << "Java_addRenderer(): surface=" << surface;
    // some processing
}

When I run the programme, I always read the following log! both SurfaceView object have same value in JNI C++ code log output:

(render_manager.cc:175): Java_addRenderer(): surface==0xbeed6120
(render_manager.cc:175): Java_addRenderer(): surface==0xbeed6120

What's the problem?

gary
  • 1,569
  • 3
  • 20
  • 30
  • What is the output of System.out.println( System.identityHashCode(svRemotePartyA) + " " + System.identityHashCode(svRemotePartyB) ) ? Inmediately after instantation, before and after the first call to addRenderer and before and after the second call. – Anonymous Coward Jul 03 '15 at 15:33

2 Answers2

2

You should not attempt to associate a meaning with the specific bit pattern of a JNI reference.

For example, in Dalvik, local references are just indices into a table on the stack. If you make the same call several times with different objects, you will see the same "value" for the reference each time, because the object reference is sitting in the same place in the local reference table.

(It's not quite that simple -- Dalvik actually tucked a trivial serial number into the reference to make it easier to tell when a local ref was used after it had been reclaimed -- but you get the idea.)

Similarly, you cannot make the assumption about global references. If you create two global references to the same object, it's very likely that those references will have different 32-bit values.

Every VM is different. Old (pre-ICS) versions of Dalvik actually passed raw pointers around, and you could compare the reference values to determine if two objects were the same. The switch to indirect references required fixing up a few things.

If you want to tell if two objects are the same, you need to have references to both, and use the JNI IsSameObject() function.

Some additional background is here.

fadden
  • 51,356
  • 5
  • 116
  • 166
2

You look at local references, which should never be used beyond the context of the same JNI method. If you get a global reference for this jobject, you will get 2 different ones.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • 1
    Great! Thanks Alex. I get their global reference and indeed they're different. – gary Jul 04 '15 at 05:12
  • 1
    If you get two global references for the *same* jobject, they may also be different. The real question is: what is the purpose of printing out the references? If attempting to differentiate between two objects in log messages, it's best to extract a serial number from the object itself. Printing global reference values doesn't help if you're getting the object from Java code, as method arguments are local refs... and if you're using the refs from native code, you already know which is which. – fadden Jul 04 '15 at 15:27
  • @fadden, you are right this is a great point: the different hexadecimal value of global reference is not an evidence of the reference holding different objects. But if they are equal, they definitely point to same objects. This is not true for local references in different JNI calls. – Alex Cohn Jul 04 '15 at 17:06
  • I agree: if you have two global references with the same value, it should be safe to assume that at that moment they reference the same object. It's a bit questionable for use in logging, as global reference values can be re-used, so if your Activity restarts and your objects are recreated you might see the same gref value for a different object and make a bad assumption. After dealing with lots of subtly broken code, I reflexively object to doing anything with JNI references except passing them back to the VM. I also worry about creating unnecessary global refs (memory leak concerns). – fadden Jul 04 '15 at 17:36