Migrating the primitive boxes to values

Brian Goetz brian.goetz at oracle.com
Fri Jan 25 18:12:51 UTC 2019


Let's take this problem from the other direction.  What are the 
impediments to us migrating the existing java.lang.Integer classes and 
friends to being values?  I think its pretty clear that "all things 
being equal", this is a better choice than creating new pox classes, and 
dealing with the sharp edges that entails.  So, what's stopping us?  
It's the usual suspects:

1.  Equality.  People do `==` on hopefully-interned Integer values.  We 
advise against it, but they do.  Having these always fail would surely 
break lots and lots of code.

2.  System.identityHashCode.  People put `Integer` in object graphs that 
get serialized; serialization will put them through IdentityHashMap.

3.  Nullability.  These types are surely nullable; I think there's no 
turning back from that.

4.  Locking.  While it seems dumb, there is surely code out there that 
locks on Integer instances.

5.  Constructor access.  There are existing constructors, which we 
deprecated in 9.  Existing binaries will invoke them with 
new/dup/invokespecial rather than the appropriate value instantiation.


My "Finding the Spirit" proposal offered a cure for 1: turn `==` into a 
substitutibility test.  For wrappers, this behaves as if all instances 
were interned, rather than just the numbers from zero to some small 
value; the spec warns that the range depends on runtime parameters.  
Combined with deprecating and eventually removing the constructors, this 
seems like it is a move that is within the range of the spec, and only 
would affect code that is relying on accidental identity.  Could we get 
away with this?

My proposed cure for (2) is similar: make identityHashCode on values 
return the "built-in hashCode" -- that is, the state-based hashCode that 
is the default for values if you don't override hashCode.

Nullability is a migration concern, shared by other types migrating to 
value types, so this is something we likely have to address regardless.

Which brings us to ... locking.  The two choices are: assign locking on 
values a state-based semantics (which no one really wants to do), or ... 
let code that locks on Integer just break. Both are obviously squirmy 
options.

Which brings me to my real point: if we go the latter route, when a big 
legacy customer with a big legacy codebase has their code broken by 
this, what happens next?  I know its really easy to say that we'll tell 
them they were making a mistake for 22 years and their bad behavior 
finally caught up with them, but this answer is rarely well received in 
reality.

It seems that if we can get comfortable with `==` being substitutibility 
(which I still think is a kind of forced move), and with outlawing 
locking on the primitive boxes -- both potentially big-ticket choices -- 
then we can rehabilitate the existing boxes.  Which would be a nice 
place to be.





More information about the valhalla-spec-observers mailing list