2

I see a lot of posts that discuss why Java's current implementation of the hashCode() method of String is correct:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i]; // (*)
        }
        hash = h; // (**)
    }
    return h;
}

However, the aforementioned explanations focus on reading the value of the hash field and how instruction reordering may cause problems if we don't use a local variable h.

My question is: what in the Java Memory Model forbids the compiler or JVM to write a temporary result to hash before line (**)?

For example, a hypothetical compiler/JVM might decide to "save local variables" and do the computation (*) not in the local variable h but directly in hash – what forbids this?

Community
  • 1
  • 1
Hbf
  • 3,074
  • 3
  • 23
  • 32
  • It would be wrong, that's what forbids it. There's nothing about that code that allows assigning of intermediate results to a class member. – user207421 Aug 26 '15 at 03:10
  • @EJP, I'm asking because I have read about similar things – assigning an intermediate result to a class member: namely the `this` field. See the discussion on the Wikipedia article [Double-checked locking](https://en.wikipedia.org/wiki/Double-checked_locking), _"For example, in Java if a call to a constructor has been inlined then the shared variable may immediately be updated once the storage has been allocated but before the inlined constructor initializes the object"._ – Why couldn't something like this happen here? – Hbf Aug 26 '15 at 05:44
  • And just to be clear, I agree with you intuitively: it feels wrong, of course. I'm just curious why it wouldn't be possible. What could be the case is that the JLS only defines _legal_ transformations and that it's actually not so easy to argue why this cannot result from legal transformations... – Hbf Aug 26 '15 at 05:51

1 Answers1

0

what forbids this?

Common sense mainly, but also these sections of the JLS (I'm quoting from SE6, but the references should be fairly consistent across versions)

17.4.2 Actions
...
This specification is only concerned with inter-thread actions. We do not need to concern ourselves with intra-thread actions (e.g., adding two local variables and storing the result in a third local variable). As previously mentioned, all threads need to obey the correct intra-thread semantics for Java programs

So, the memory model defers to the rest of the JLS for the definition of what is conforming behaviour with respect to assignment of local variables, etc.

15.26.1 Simple Assignment Operator
...
If the left-hand operand expression is a field access expression
... the right hand operand is evaluated. ...
... the variable denoted by e.f is assigned the value of the right hand operand as computed above.

...

Otherwise
... the value of the right-hand operand is converted to the type of the left-hand variable ... and the result of the conversion is stored into the variable

The conforming behaviour for a field assignment is defined to assign the right-hand expression to the field.

The conforming behaviour for a variable assignment is defined to assign to the variable.

Based on these requirements, I can't see how a conforming implementation would be allowed to skip the use of the local variable h.

Tim
  • 6,406
  • 22
  • 34
  • That sounds very reasonable to me, so please forgive if I play the devil's advocate! – From a intra-thread perspective, it seems completely ok to store intermediate results in `hash` – you wouldn't be able to observe the difference, right? – Hbf Aug 26 '15 at 05:42
  • By the way, assigning an intermediate result to the `this` variable _may_ happen, see the discussion on the Wikipedia article [Double-checked locking](https://en.wikipedia.org/wiki/Double-checked_locking): _"For example, in Java if a call to a constructor has been inlined then the shared variable may immediately be updated once the storage has been allocated but before the inlined constructor initializes the object"._ – Hbf Aug 26 '15 at 05:43