Java hashCode()算法

Java hashCode()算法,java,hashcode,pseudocode,Java,Hashcode,Pseudocode,我正在寻找Object.hashCode()的算法 此代码是中的本机代码 这是因为 (a) 代码在程序集中-- 从未在Java或任何其他HLL中使用过 或 (b) 只是没有透露 ? 在这两种情况下,我都希望掌握“hashCode()是如何计算的”的算法(伪代码或一些详细的解释)——计算中的参数和计算本身是什么 请注意:这是我要找的-- 不像字符串或hashMap/table那样 //=========================================================

我正在寻找Object.hashCode()的算法

此代码是中的本机代码

这是因为

(a) 代码在程序集中-- 从未在Java或任何其他HLL中使用过

(b) 只是没有透露

?

在这两种情况下,我都希望掌握“hashCode()
是如何计算的”的算法(伪代码或一些详细的解释)——计算中的参数和计算本身是什么

请注意:这是我要找的-- 不像字符串hashMap/table那样

//==========================================================================

jdk 8现在说

"The value returned by hashCode() is the object's hash code, which is the object's memory address in hexadecimal." 

这是因为它依赖于不暴露于Java代码的低级细节。标准库的一些基本部分(如
java.lang.Object
)必须在本机代码中实现


另一方面,您可以找到至少一个更详细地介绍热点实现的方法。

hashCode
是本机方法,这意味着系统库是在内部调用的。这是因为hashcode内部会根据对象内存位置尝试生成一个数字。此代码依赖于机器,可能是用C编写的

但如果您真的对本机代码感兴趣,请遵循以下步骤:


尽管有Javadoc,但algo只能将地址用作输入。这意味着,即使新对象在eden空间中使用相同的地址,它们也不会有相同的哈希代码

它可能使用了许多算法,但并非所有算法都使用地址

注意:hashCode()是31位的

顺便说一句,您可以在热点上使用
Unsafe.putin(对象,1,值)
设置它

Set<Integer> ints = new LinkedHashSet<>();
int negative = 0, nonneg = 0;
for (int i = 0; i < 100; i++) {
    System.gc();
    for (int j = 0; j < 100; j++) {
        int h = new Object().hashCode();
        ints.add(h);
        if (h < 0) negative++;
        else nonneg++;
    }
}
System.out.println("unique: " + ints.size() + " negative: " + negative + " non-neg: " + nonneg);
使用不安全的

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

Object o = new Object();
System.out.println("From header " + Integer.toHexString(unsafe.getInt(o, 1L)));
// sets the hashCode lazily
System.out.println("o.hashCode()  " + Integer.toHexString(o.hashCode()));
// it's here now.
System.out.println("after hashCode() From header " + Integer.toHexString(unsafe.getInt(o, 1L)));
unsafe.putInt(o, 1L, 0x12345678);
System.out.println("after change o.hashCode()  " + Integer.toHexString(o.hashCode()));
印刷品

unique: 10000 negative: 0 non-neg: 10000
From header 0
o.hashCode()  2260e277
after hashCode() From header 2260e277
after change o.hashCode()  12345678

本机
hashCode
方法实现取决于
JVM
。默认情况下,在HotSpot中它返回随机数,您可以在(函数
get_next_hash
)中检查它。

我认为它是本机的,因为对象的hashCode是内存地址标识符,而不是对象字段的散列。需要有人更新您引用的文档。因为这是完全错误的。“hashCode()只使用对象的地址”将与当前的规范保持一致。但是你会说“即使新对象使用相同的地址,它们也不会有相同的哈希代码”。那么这条领带是怎么断的?对象的引用地址以外的其他一些内存位置(如某个成员的引用地址、它使用的结束地址/内存量、时间戳上的某些内容…?)虽然在一次执行中每次调用hashCode()时都会遇到相同的hashCode,仅用于此计算的对象地址感觉不太正确——与内存空间太一致,哈希代码的随机性不强。它将是一个不可变的“句柄”标识符,在对象的生命周期内保持不变。最有可能的是VM实现依赖,并且可能与内存地址没有任何关系,因为由于GC操作,java中的所有对象都可以在物理内存中重新定位。@peterk我相信在很早的版本中,对象无法移动,而且地址确实是哈希的一部分。(在Java1.2之前)很可能是在过去,因为它很容易实现,但现在肯定不是这样,也不合适。唯一可以假设的是,它在对象的生命周期内是不变的,并且在VM实例中的所有对象中是唯一的?它是怎么做到的——也许在地址的低端?