发布于2026-07-09 阅读(0)
扫一扫,手机访问
System.identityHashCode() 返回的是 JVM 为对象分配的一个唯一、稳定且与 equals/hashCode 无关的整数标识,而非真实的物理内存地址。其底层通常基于对象首次被访问时的内存地址(或其变换值),但绝不能等同于真实地址,也不能跨 JVM 或跨运行时保持一致。
再强调一遍:System.identityHashCode() 并不返回对象的“物理内存地址”,而是 JVM 为该对象分配的一个唯一、稳定、与 equals/hashCode 无关的整数标识。这个标识底层通常基于对象首次被访问时的内存地址(或其变换值),但不能等同于真实内存地址,也不保证跨 JVM 或跨运行时一致。
JVM 规范本身并没有强制要求 identityHashCode 必须是内存地址。以 HotSpot 为例:对于未被 GC 移动的对象,它通常由对象头中的“mark word”部分生成,可能包含压缩后的地址信息;而一旦对象经过垃圾回收(如 G1、ZGC)移动过位置,JVM 会保留原始的 identityHashCode 值,而不是更新为新地址。更关键的是,当启用指针压缩(-XX:+UseCompressedOops)时,地址本身已被压缩,更无法直接映射为 32 位的 int。
它的核心价值在于:在需要区分“同一性(==)”而非“相等性(equals)”的场景下,提供一个轻量级的对象标识。具体来说:
hashCode() 导致的冲突,比如 WeakHashMap 内部就依赖它;equals 被重写后,这个功能非常实用;toString() 被重写带来的混淆;jmap/jstack 观察相同 identityHashCode 是否长期存在。以下几种用法要么不可靠,要么完全错误:
identityHashCode 反推出真实内存位置,何况 GC 和指针压缩会不断改变地址;identityHashCode 也完全不相关;Object a = new Object(); Object b = new Object(); Object c = a; // 引用相同 System.out.println(System.identityHashCode(a)); // 如:123456789 System.out.println(System.identityHashCode(b)); // 如:987654321(通常不同) System.out.println(System.identityHashCode(c)); // 同 a,如:123456789 System.out.println(a == c); // true System.out.println(a.equals(c)); // true(Object 默认实现即 ==)
注意:即使 a 和 b 是同一类的两个新实例,它们的 identityHashCode 几乎总是不同;当然,极端哈希冲突(极罕见)发生时,JVM 内部也有机制确保仍能区分对象身份。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8