System.identityHashCode() 对原语的行为
System.identityHashCode() behavior on primitives
在 jvm imgui 中,我使用的是
System.identityHashCode(i++)
哪里
var i = 0
为每个帧始终生成给定对象的常量 ID(因此
能够跟踪它)
然而,一个 user case 刚刚告诉我这仅对 [0, 125]
中的值有效
为了调试并找到错误,我结束了对这段代码的测试:
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]}")
}
还有:
- 字节(完全有效,所有 256 个值的 A == B)
- 短裤(128 起无效)
- 整数(不适用于 128)
- 多头(从 128 开始不工作)
- 浮动(根本不工作)
- 加倍(根本不起作用)
这是为什么?
假设这种行为在其他平台上也是一致的,我是否安全?
However, one user case just showed me that this is valid only for values in [0, 125]
System.identityHashCode(Object)
采用 Object
而不是原语,这意味着您的 i++
被自动装箱为 Integer
(或 Long
或 . ..).对象具有相同身份哈希码的唯一时间最有可能(但不总是)是当它们是同一对象时。碰巧的是,JVM 出于优化目的缓存了少量 Integer
,这意味着 0 到 127 值的身份哈希码是相同的。
编译器发生自动装箱时 generates a call to Integer.valueOf(int)
。如果我们查看 `valueOf(...) 的代码,我们会看到:
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
所以有一个低缓存范围和高缓存范围,您将从中获得缓存的 constant 对象,这些对象在 JVM 启动时生成。 JVM 参数会影响数字缓存的大小。因此 127 必须在您的 JVM 的缓存范围内,而 128 及以上则不在。
// both of the 100 values gets auto-boxed to the same Integer object
System.identityHashCode(100) == System.identityHashCode(100)
这基本上等同于比较同一对象的哈希码:
Integer i = new Integer(100);
System.identityHashCode(i) == System.identityHashCode(i)
一旦您超过了 Integer
值的初始缓存集并指定了更大的整数,新的 Integer 对象将在自动装箱时创建,因此身份哈希码(很可能)不再等于。
// by default, each of these 1000000 values gets auto-boxed to a different object
System.identityHashCode(1000000) != System.identityHashCode(1000000)
这基本上等同于实例化 2 个不同的整数并期望它们的哈希码相同:
Integer i1 = new Integer(1000000);
Integer i2 = new Integer(1000000);
System.identityHashCode(i1) != System.identityHashCode(i2)
请注意 System.identityHashCode(...)
而不是 return 唯一值,因此如果在查看时它们可能(尽管不太可能)生成相同的值不同的对象。
在 jvm imgui 中,我使用的是
System.identityHashCode(i++)
哪里
var i = 0
为每个帧始终生成给定对象的常量 ID(因此
能够跟踪它)
然而,一个 user case 刚刚告诉我这仅对 [0, 125]
为了调试并找到错误,我结束了对这段代码的测试:
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]}")
}
还有:
- 字节(完全有效,所有 256 个值的 A == B)
- 短裤(128 起无效)
- 整数(不适用于 128)
- 多头(从 128 开始不工作)
- 浮动(根本不工作)
- 加倍(根本不起作用)
这是为什么?
假设这种行为在其他平台上也是一致的,我是否安全?
However, one user case just showed me that this is valid only for values in [0, 125]
System.identityHashCode(Object)
采用 Object
而不是原语,这意味着您的 i++
被自动装箱为 Integer
(或 Long
或 . ..).对象具有相同身份哈希码的唯一时间最有可能(但不总是)是当它们是同一对象时。碰巧的是,JVM 出于优化目的缓存了少量 Integer
,这意味着 0 到 127 值的身份哈希码是相同的。
编译器发生自动装箱时 generates a call to Integer.valueOf(int)
。如果我们查看 `valueOf(...) 的代码,我们会看到:
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
所以有一个低缓存范围和高缓存范围,您将从中获得缓存的 constant 对象,这些对象在 JVM 启动时生成。 JVM 参数会影响数字缓存的大小。因此 127 必须在您的 JVM 的缓存范围内,而 128 及以上则不在。
// both of the 100 values gets auto-boxed to the same Integer object
System.identityHashCode(100) == System.identityHashCode(100)
这基本上等同于比较同一对象的哈希码:
Integer i = new Integer(100);
System.identityHashCode(i) == System.identityHashCode(i)
一旦您超过了 Integer
值的初始缓存集并指定了更大的整数,新的 Integer 对象将在自动装箱时创建,因此身份哈希码(很可能)不再等于。
// by default, each of these 1000000 values gets auto-boxed to a different object
System.identityHashCode(1000000) != System.identityHashCode(1000000)
这基本上等同于实例化 2 个不同的整数并期望它们的哈希码相同:
Integer i1 = new Integer(1000000);
Integer i2 = new Integer(1000000);
System.identityHashCode(i1) != System.identityHashCode(i2)
请注意 System.identityHashCode(...)
而不是 return 唯一值,因此如果在查看时它们可能(尽管不太可能)生成相同的值不同的对象。