I did a bit of investigation into OpenJDK's JVM source code to understand these strange results, and it turns out I was wrong to suggest using jobject as a key.
Apparently, each JNI thread maintains a an array of 32 slots called "handles". When a native call is being made, the JVM puts any java object argument(s) into a slot,
and it's the address of the
slot that reaches our native method as a jobject. That's the reason your 2 native calls resulted in the same value for the jobject, because
each call put a different object into the same slot.
But what exactly is that jobject value?
It's actually a pointer to an "oop". And an oop is itself another pointer, one to an "oopDesc" struct. Every java object is mirrored in the JVM native code by an oopDesc instance.
So to get to a java object's native representation via a jobject handle, one has to do
To summarize, you can't use the jobject itself as a key, because it's just a reused slot. Probably, you can use "long key = *(long*)jobj" because that is the address of the oopDesc that mirrors the java instance
and should hence be unique. But I'm not sure how GC affects this uniqueness. In any case, it smells like a hack to me. So I think you're better off using hashCode itself, rather than jobject or anything accessible via the jobject
. Sorry for the misleading suggestion.