Comportamiento System.identityHashCode () en primitivas

En jvm imgui , estaba usando

System.identityHashCode(i++)

dónde

var i = 0

generar para cada marco siempre una identificación constante para un object dado (y por lo tanto
capaz de rastrearlo)

Sin embargo, un caso de usuario me acaba de mostrar que esto es válido solo para valores en [0, 125]

Al intentar depurar y encontrar el error, terminé probando este breve fragment de código:

  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]}") } 

también con:

  • bytes (en pleno funcionamiento, A == B para todos los 256 valores)
  • pantalones cortos (no funciona desde 128)
  • Ints (no funciona desde 128)
  • largos (no funciona desde 128)
  • flota (no funciona en absoluto)
  • dobles (no funciona en absoluto)

¿Porqué es eso?

¿Y estoy seguro suponiendo que este comportamiento será coherente también en otras plataforms?

Sin embargo, un caso de usuario me acaba de mostrar que esto es válido solo para valores en [0, 125]

System.identityHashCode(Object) toma un Object no una primitiva, lo que significa que su i++ está autoencantado para ser un Integer (o Long o …). La única vez que los objects tendrán el mismo código de identidad de hash probablemente sea (pero no siempre) cuando sean el mismo object. Da la casualidad que la JVM almacena en caching un pequeño número de Integer para fines de optimization, lo que significa que los códigos de identidad de los valores de 0 a 127 son los mismos.

Cuando ocurre el autoboxing, el comstackdor genera una llamada a Integer.valueOf(int) . Si miramos el código para `valueOf (…) vemos:

 if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); 

De modo que hay un range de caching bajo y alto desde el que obtendrá un object constante en caching que se genera cuando se inicia la JVM. Hay arguments de JVM que afectan el tamaño de los cachings numéricos. Entonces, 127 debe estar dentro del range de caching para su JVM, mientras que 128 no lo están.

 // both of the 100 values gets auto-boxed to the same Integer object System.identityHashCode(100) == System.identityHashCode(100) 

Esto es básicamente equivalente a comparar los códigos hash del mismo object:

 Integer i = new Integer(100); System.identityHashCode(i) == System.identityHashCode(i) 

Una vez que haya pasado el set de valores integers en la memory caching inicial y se especifican datos más grandes, se crearán nuevos objects integers cuando estén en caja automática y, por lo tanto, los códigos hash de identidad ya no sean iguales (lo más probable).

 // by default, each of these 1000000 values gets auto-boxed to a different object System.identityHashCode(1000000) != System.identityHashCode(1000000) 

Esto es básicamente equivalente a crear instancias de dos integers diferentes y esperar que sus códigos hash sean los mismos:

 Integer i1 = new Integer(1000000); Integer i2 = new Integer(1000000); System.identityHashCode(i1) != System.identityHashCode(i2) 

Tenga en count que System.identityHashCode(...) no devuelve valores únicos, por lo que es posible (aunque poco probable) que generen el mismo valor si se observan objects diferentes.