商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 如何在 Java 中利用 System.identityHashCode() 获取对象的物理内存哈希值标识

如何在 Java 中利用 System.identityHashCode() 获取对象的物理内存哈希值标识

  发布于2026-07-09 阅读(0)

扫一扫,手机访问

System.identityHashCode() 返回的是 JVM 为对象分配的一个唯一、稳定且与 equals/hashCode 无关的整数标识,而非真实的物理内存地址。其底层通常基于对象首次被访问时的内存地址(或其变换值),但绝不能等同于真实地址,也不能跨 JVM 或跨运行时保持一致。

如何在 Ja va 中利用 System.identityHashCode() 获取对象的物理内存哈希值标识

再强调一遍:System.identityHashCode() 并不返回对象的“物理内存地址”,而是 JVM 为该对象分配的一个唯一、稳定、与 equals/hashCode 无关的整数标识。这个标识底层通常基于对象首次被访问时的内存地址(或其变换值),但不能等同于真实内存地址,也不保证跨 JVM 或跨运行时一致。

为什么 identityHashCode 不等于内存地址?

JVM 规范本身并没有强制要求 identityHashCode 必须是内存地址。以 HotSpot 为例:对于未被 GC 移动的对象,它通常由对象头中的“mark word”部分生成,可能包含压缩后的地址信息;而一旦对象经过垃圾回收(如 G1、ZGC)移动过位置,JVM 会保留原始的 identityHashCode 值,而不是更新为新地址。更关键的是,当启用指针压缩(-XX:+UseCompressedOops)时,地址本身已被压缩,更无法直接映射为 32 位的 int。

如何正确使用 identityHashCode?

它的核心价值在于:在需要区分“同一性(==)”而非“相等性(equals)”的场景下,提供一个轻量级的对象标识。具体来说:

  • 实现自定义哈希容器时,避免用户重写 hashCode() 导致的冲突,比如 WeakHashMap 内部就依赖它;
  • 调试时快速判断两个引用是否指向同一个对象实例——尤其当 equals 被重写后,这个功能非常实用;
  • 在日志中打印对象唯一标识,避免 toString() 被重写带来的混淆;
  • 用于对象生命周期监控或内存泄漏初步排查,配合 jmap/jstack 观察相同 identityHashCode 是否长期存在。

常见误区与注意事项

以下几种用法要么不可靠,要么完全错误:

  • 不要用它还原内存地址:目前没有公开 API 能从 identityHashCode 反推出真实内存位置,何况 GC 和指针压缩会不断改变地址;
  • 不要用于跨 JVM 比较:不同 JVM 实例中即使相同的对象,其 identityHashCode 也完全不相关;
  • 不要假设它单调递增或连续:分配顺序、GC 行为、线程竞争都会影响值的分布;
  • 慎用于持久化或网络传输:它只对当前 JVM 生命周期有效,序列化后即失效。

简单验证示例

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 默认实现即 ==)

注意:即使 ab 是同一类的两个新实例,它们的 identityHashCode 几乎总是不同;当然,极端哈希冲突(极罕见)发生时,JVM 内部也有机制确保仍能区分对象身份。

本文转载于:https://www.php.cn/faq/2401967.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注