hashCode()的默认行为

5

我在同一台机器上持续运行这个程序:

class Test {
    public static void main(String[] args) {
        Test test = new Test();
        System.out.println(test.hashCode());
    }
}

每次在我的机器上运行程序(Windows 7 64位),结果都相同:4384790。
在另一台机器上(Windows server 2008, 64位),大多数情况下会给我1671711。但有时结果是11394033。
我在我的机器上使用Java HotSpot(TM) Client VM 1.6.0_26/1.6.0_33运行程序。
我已经阅读了Object类的文档:
“尽可能合理地说,由Object类定义的hashCode方法确实为不同对象返回不同的整数。(通常通过将对象的内部地址转换为整数来实现,但这种实现技术不是JavaTM编程语言所必需的。)”
但如果hashCode()确实是通过将对象的内部地址转换为整数来实现的,我仍然不理解为什么Java虚拟机每次运行时都分配相同的地址给Test对象。
默认的hashCode()操作方式是否已知?

非常小心地说,它没有被明确指定,并且正如您所发现的那样,它因平台而异。 - user207421
我认为“内部地址”并不是 RAM 中的物理地址,而是 JVM 内部的一些东西,可能每次都从相同的“逻辑”值开始 - 因此,如果您总是在同一类中创建相同的对象,它将始终成为基于“逻辑”地址方案的“第一个”对象(再次:我只是在推测)。 - user330315
@Perception:那个问题的被接受的答案不适用于现代JVM。请看下面我的回答以获取解释(简而言之,Object.hashCode()根本不使用对象的地址)。 - NPE
2个回答

5
细节是基于JVM的。此外,一些(大多数?)JVM支持多个hashCode()算法(在启动JVM时,可以选择使用哪个算法)。有趣的是,其中大多数算法——包括Oracle的默认算法——根本不使用对象的地址。例如,JDK7的默认hashCode()会使用全局伪随机数生成器,然后将生成的伪随机哈希码缓存到对象的头中。当然,如果以相同的方式初始化,则伪随机生成器始终会给出相同的数字序列。有关我过去所做调查的详细信息,请参见Java中的“内部地址”是什么?

3

非内核程序从不使用绝对内存地址,它们使用虚拟内存,其中每个进程都有自己的地址空间。因此,一个程序在每次运行时都会将数据放置在相同的位置。


尽管这是真实的,但它与Object.hashCode()没有任何关系(至少在现代Oracle JVM中)。有关详细信息,请参见我的答案。 - NPE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接