java中object类默认hashcode()不直接返回内存地址,而是jvm生成并缓存的、与对象身份绑定的32位identity hash code,基于初始地址、线程id、随机种子等混合计算,gc移动后仍保持不变。

Java 中 Object 类默认的 hashCode() 方法**不直接返回内存地址**,而是由 JVM 生成一个与对象“身份”绑定的、稳定且唯一的 32 位整数,称为 identity hash code。
它不是真实内存地址的原因
现代 JVM(如 HotSpot)出于安全、垃圾回收和跨平台兼容性考虑,刻意避免暴露物理地址:
- GC 可能随时移动对象,物理地址会变,但 identity hash code 必须保持不变(只要对象未被重写
hashCode()); - 64 位系统下指针是 8 字节,而
int只有 4 字节,无法无损存储原始地址; - JVM 需要保证不同平台、不同运行环境下行为一致,不能依赖底层硬件地址格式。
HotSpot 中典型的生成逻辑
以 OpenJDK HotSpot 为例,首次调用 hashCode() 时,JVM 会执行 get_next_hash() 函数,策略取决于启动参数 -XX:hashCode(默认值为 5),常见方式包括:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 使用对象初始分配位置、线程 ID、随机种子混合计算;
- 对对象头中存储的随机数与地址做异或/移位运算;
- 取对象所在内存页地址 + 线程局部哈希种子,再截取低 32 位;
- 结果写入对象头的 mark word 中缓存,后续调用直接复用。
如何获取和验证这个值
即使对象重写了 hashCode(),仍可通过以下方式拿到原始 identity hash code:
- 调用
System.identityHashCode(obj)—— 它返回的就是 JVM 分配的该值; - 两个内容相同但新建的对象(如
new String("a")两次),其System.identityHashCode()几乎总是不同; - 同一对象经历多次 GC 后,
System.identityHashCode()仍保持不变,证明它被缓存且与运行时地址解耦。
为什么说“默认返回内存地址”这种说法不准确
API 文档或早期资料中常称“返回内存地址”,这是为了便于理解的简化说法。实际上:
-
hashCode()是native方法,具体实现由 JVM 提供; - 它的值在对象创建后首次调用时才计算并固化;
- 它与
equals()和重写的hashCode()无关,只标识对象“是不是同一个实例”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










