In jvm imgui, I was using
System.identityHashCode(i++)
where
var i = 0
to generate for each frame always a constant id for a given object (and so being
able to track it)
However, one user case just showed me that this is valid only for values in [0, 125]
Trying to debug and find the bug, I ended testing this short snippet of code:
var i = 0
val A = Array(256, { System.identityHashCode(i++) })
i = 0
val B = Array(256, { System.identityHashCode(i++) })
repeat(256) {
if (A[it] != B[it])
println("[$it] different, A ${A[it]}, B ${B[it]}")
}
also with:
Why is that?
And am I safe assuming this behavior will be the coherent also on other platforms?
However, one user case just showed me that this is valid only for values in [0, 125]
System.identityHashCode(Object)
takes an Object
not a primitive which means that your i++
is auto-boxed to be an Integer
(or Long
or ...). The only time that the objects will have the same identity hashcode will most likely (but not always) be when they are the same object. As it happens, the JVM caches a small number of Integer
s for optimization purposes meaning that the identity hashcodes of the 0 to 127 values are be the same.
When autoboxing happens the compiler generates a call to Integer.valueOf(int)
. If we look at the code for `valueOf(...) we see:
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
So there is a low and high cache range from which you will get a cached constant object that are generated when the JVM starts up. There are JVM arguments that affect the size of the number caches. So 127 must be within the cache range for your JVM while 128 and above are not.
// both of the 100 values gets auto-boxed to the same Integer object
System.identityHashCode(100) == System.identityHashCode(100)
This is basically equivalent to comparing the hashcodes of the same object:
Integer i = new Integer(100);
System.identityHashCode(i) == System.identityHashCode(i)
Once you are past the initial cached set of Integer
values and larger ints are specified, new Integer objects will be created when they are auto-boxed and so the identity hashcodes are (most likely) no longer equal.
// by default, each of these 1000000 values gets auto-boxed to a different object
System.identityHashCode(1000000) != System.identityHashCode(1000000)
This is basically equivalent to instantiating 2 different integers and expecting their hashcodes to be the same:
Integer i1 = new Integer(1000000);
Integer i2 = new Integer(1000000);
System.identityHashCode(i1) != System.identityHashCode(i2)
Note that System.identityHashCode(...)
does not return unique values so it is possible (albeit unlikely) that they will generate the same value if when looking at different objects.