String 类中的“哈希”变量

Pee*_*ush 3 java jvm

java.lang.String 类中私有“哈希”变量的用途是什么。它是私有的,每次调用 hashcode 方法时都会计算/重新计算。

http://hg.openjdk.java.net/jdk7u/jdk7u6/jdk/file/8c2c5d63a17e/src/share/classes/java/lang/String.java

Jac*_* G. 5

它用于缓存hashCodeString。因为String是不可变的,它hashCode永远不会改变,所以在它已经计算出来之后再试图重新计算它是没有意义的。

在你已经发布的代码,它只是重新计算时的价值hash就是0,它可以如果发生任何hashCode尚未计算或者如果hashCodeString实际上是0,这是可能的!

例如,所述hashCode"aardvark polycyclic bitmap"0

通过引入一个hashIsZero字段,这个疏忽似乎在 Java 13 中得到了纠正:

public int hashCode() {
    // The hash or hashIsZero fields are subject to a benign data race,
    // making it crucial to ensure that any observable result of the
    // calculation in this method stays correct under any possible read of
    // these fields. Necessary restrictions to allow this to be correct
    // without explicit memory fences or similar concurrency primitives is
    // that we can ever only write to one of these two fields for a given
    // String instance, and that the computation is idempotent and derived
    // from immutable state
    int h = hash;
    if (h == 0 && !hashIsZero) {
        h = isLatin1() ? StringLatin1.hashCode(value)
                       : StringUTF16.hashCode(value);
        if (h == 0) {
            hashIsZero = true;
        } else {
            hash = h;
        }
    }
    return h;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个疏忽。这是必须重新计算某些字符串的值和为每个字符串实例添加附加字段之间的权衡。但从那时起,字符串类的字段以及 JVM 实现的内存布局已多次更改,此外,这个问题的相关性已被重新考虑,因为它可能使应用程序遭受 DoS 攻击。所以现在,额外的字段已经被认为是没有问题的,特别是根据JVM,某些字段可能对所需的存储没有影响。 (3认同)