我经常听说这些方法 (Object.hashCode
和System.identityHashCode
) 返回对象的地址,或者从地址快速计算出来的东西;但我也很确定垃圾收集器会移动和压缩对象。由于哈希码不能改变,这就带来了一个问题。我知道这不是日常工作需要知道的事情,但我想了解内部情况。那么,有谁知道这是如何在 Java 中实现的?或 .NET,因为它们可能相似。
3 回答
.NET 的实现是故意不发布的(当您尝试反编译它时,您会发现它进行了非托管框架调用)。唯一的文档是这里,它只声明“不能保证为每个对象产生不同的值”,并且“可能会在框架版本之间发生变化”。对它的实际工作方式做出任何假设可能都是不明智的。
Java 更容易理解(尽管可能在不同的 JVM 中可能有所不同),并且在这个问题中特别提到:Will .hashcode() return a different int due to compaction of tenure space?
Java 实现的要点是,按照约定,对象的哈希码的值在第一次检索之前是不相关的。之后,它必须保持不变。因此,在第一次调用对象的 hashcode() 方法之前,移动对象的 GC 并不重要。之后,使用缓存值。
对象的 identityHashCode 不会改变。因此,任何移动都在该水平之下进行。
一个基本的实现将有一个逻辑地址 --> 每个对象的物理地址映射。
更复杂的实现只会在页面级别进行映射,因此最后 6 位可能是内存偏移量,其余的是页面 ID。间接将发生在页面 id --> 实际页面地址级别。
在 .net 中,getHash() 方法会受到 GC 的影响,因此建议开发人员使用自己的哈希实现。我现在找不到内部实现的链接。以后找到的话我会发的。。
找到链接......这个问题在这里得到了回答