[concurrency-interest] Does JDK 9 String.hashCode() have a bug?

David Holmes davidcholmes at aapt.net.au
Wed Sep 28 07:29:27 EDT 2016

I thought that one of the properties of the JMM is that a second read of a variable can not return an earlier write to that variable. Certainly it is a property I recall being discussed in JSR-133.




From: Concurrency-interest [mailto:concurrency-interest-bounces at cs.oswego.edu] On Behalf Of Peter Levart
Sent: Wednesday, September 28, 2016 8:33 PM
To: concurrency-interest <Concurrency-interest at cs.oswego.edu>
Subject: [concurrency-interest] Does JDK 9 String.hashCode() have a bug?



I would like to discuss the implementation of String.hashCode() method in the light of JMM. Here it is (the recent one from JDK 9 which includes implementation of compact strings):


    public int hashCode() {
        if (hash == 0 && value.length > 0) {
            hash = isLatin1() ? StringLatin1.hashCode(value)
                              : StringUTF16.hashCode(value);
        return hash;


Here, 'hash' is a plain instance field in String. Suppose we have a freshly constructed non-zero length String object, whose reference 's' is accessible to two threads and each of them concurrently invokes hashCode() on it:


Thread 1:

int h1 = s.hashCode();


Thread 2:

int h2 = s.hashCode();


Suppose also that the isLatin1() ? StringLatin1.hashCode(value) : StringUTF16.hashCode(value) computation returns a non-zero value.


Is it possible that the outcome (h1, h2) is either (0, hc) or (hc, 0) where the hc is the non-zero result of above mentioned computation?

According to JMM, I think it is. Since there is no synchronization between a write w(hash, hc) by one thread and two reads r1(value):v1 and r2(value):v2 by the other thread that correspond to program lines:

    if (hash == 0 ....


    return hash;


...the reads may or may not see the write independently. So there is a possibility that v1 == hc and v2 == 0.


Am I right and should this be fixed?


Note that JDK 8 code is different. It does not have this problem:


public int hashCode() {
        int h = hash;
        if (h == 0) {
            for (char v : value) {
                h = 31 * h + v;
            if (h != 0) {
                hash = h;
        return h;


Regards, Peter


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20160928/e35d33ce/attachment.html>

More information about the Concurrency-interest mailing list