【问题标题】:System.identityHashCode() can the same hashCode be returned after an Object is GC'edSystem.identityHashCode() 可以在对象被 GC 后返回相同的 hashCode
【发布时间】:2015-12-17 08:06:52
【问题描述】:

假设 System.identityHashCode(object1)==123object1 已被垃圾回收。新创建的object2 是否有可能与object1 在被GC 之前拥有相同的身份哈希码?

【问题讨论】:

  • 是的,完全有可能。
  • 甚至有可能同时存在的两个对象拥有相同的identityHashCode
  • 请注意System.identityHashCode() 的行为与Object.hashCode() 的行为相同——它只是忽略了子类中的任何hashCode() 覆盖

标签: java jvm hashcode


【解决方案1】:

新创建的 object2 是否有可能与 object1 在被 GC 之前获得的身份哈希码相同?

是的。

身份哈希码可能派生自对象第一次调用该方法时的对象地址。 (或者它可能以其他方式生成。规范允许使用许多不同的机制。)

所以,如果 GC 收集到object1,并在与原始对象相同的地址分配了一个新对象object2,那么新对象可能与原始对象具有相同的哈希码.

此外,如果在生成哈希码后 GC 移动 object1,则 object1 的原始对象 (object2)。然后,您可能会得到两个具有相同哈希码的 现有 对象。

但是这些都不是问题。哈希码并非旨在成为对象的标识符。 (所以不要尝试这样使用它们。)


我对身份的理解是,对象在 JVM 中在给定的时间点是唯一的。

身份是独一无二的。身份哈希码不是。正如Object javadoc 所说:

“在相当实用的情况下,Object 类定义的hashCode 方法确实为不同的对象返回不同的整数。”

这远不能保证唯一性。

然后:

"(这通常通过将对象的内部地址转换为整数来实现,但 Java™ 编程语言不需要这种实现技术。)"

它指的是第一次调用hashCode()时对象的地址。 hashCode() 方法的合同规定哈希码值不能更改。身份哈希码......实际上......作为对象的一部分被记住,以便 GC 可以移动对象。

请注意,最新的 javadocs 已经删除了所有关于身份哈希码如何生成或可能生成的内容。此更改发生在 Java 12

【讨论】:

  • 有这方面的官方文档吗?我对 identity 的理解是,在给定的时间点,对象在 JVM 中是唯一的。 @Mark Rotteveel 在他的评论中说,identiyHashCode cof 2 对象在运行时可以是相同的,这与 -> 身份哈希码是分配对象的地址相反。
  • 但身份哈希码不是分配对象的地址 - 声明是“它(通常)派生来自地址......”。另请参阅stackoverflow.com/questions/25111131/… 处的说明
  • “这与 -> 身份哈希码是分配对象的地址相反” - 不,不是。 (即使忽略“派生自”点。) GC 可以移动一个对象,然后可以在第一个对象的原始地址分配一个新对象。如果发生这种情况,两个对象最终可能会使用相同的身份哈希码。
【解决方案2】:

根据定义,这是可能的。

identityHashCode 是一个int。 Java 中只有 232 个不同的整数。
您可以轻松编写一个创建超过 232 个对象的程序。

【讨论】:

    猜你喜欢
    • 2011-05-20
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    • 2017-10-08
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多