java.lang.String hashCode and @Stable ?

Viktor Klang viktor.klang at oracle.com
Fri Apr 11 14:26:50 UTC 2025


Another option is to make the internal stored hash a long and then the first part can be used to track whether it has been computed and then just cast the long to an int to retrieve the value. If it has been computed, one bit is flipped in the upper 32 bits. Then a read is just a single long read + int cast, and a write is just the computed hashCode plus an OR.

The main downside of course is that it adds 3 bytes to each string (of course alignment and padding etc might change that overhead).


@Stable private long hash; // Default to 0

public int hashCode() {
    long h = hash;
    if ((h & ~(1L << 32)) == 0) // if calculated bit is not set, the calculate
        hash = h = (1L << 32) | (isLatin1()
            ? StringLatin1.hashCode(value)
            : StringUTF16.hashCode(value));
    return (int)h;
}


Cheers,
√


Viktor Klang
Software Architect, Java Platform Group
Oracle
________________________________
From: core-libs-dev <core-libs-dev-retn at openjdk.org> on behalf of forax at univ-mlv.fr <forax at univ-mlv.fr>
Sent: Friday, 11 April 2025 11:04
To: Chen Liang <chen.l.liang at oracle.com>
Cc: core-libs-dev <core-libs-dev at openjdk.org>
Subject: Re: java.lang.String hashCode and @Stable ?



________________________________
From: "Chen Liang" <chen.l.liang at oracle.com>
To: "Remi Forax" <forax at univ-mlv.fr>, "core-libs-dev" <core-libs-dev at openjdk.org>
Sent: Thursday, April 10, 2025 8:16:39 PM
Subject: Re: java.lang.String hashCode and @Stable ?
Hi Remi,
I think this is probably due to these fields being added too early - the stable on string byte array is also added lately.

That said, I don't think adding stable on both fields completely resolves the constant folding issues around string hash code. The current code can only constant fold non-zero hash; a zero hash is folded to a read to hash field, which cannot fold further because it's a read of the default value from a stable field.
A solution may be to change hashIsZero to a byte field indicating 3 states - hash unset (0), hash computed to field, hash computed and is zero. This allows the zero hash to constant fold as well at the cost of non-constant hash access performance, as now there are two reads.

yes,
and obviously, it has to be done without introducing a perf regression if the String is not constant folded.

I think it would be nice to try that as a follow-up of JDK-8354300.


Also this reminds me of https://bugs.openjdk.org/browse/JDK-8332249 - maybe Method::hashCode was hot because the string hash code could not fold.

Usually in framework like Spring, Method are cached either by the framework or by java.lang.Class own cache so the Method itself is rarely a constant.


Regards, Chen

regards,
Rémi

________________________________
From: core-libs-dev <core-libs-dev-retn at openjdk.org> on behalf of Remi Forax <forax at univ-mlv.fr>
Sent: Thursday, April 10, 2025 4:18 AM
To: core-libs-dev <core-libs-dev at openjdk.java.net>
Subject: java.lang.String hashCode and @Stable ?

Question,
why String.hash and String.hashIsZero are not declared @Stable ?

regards,
Rémi

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20250411/a061078d/attachment.htm>


More information about the core-libs-dev mailing list