Should JLS 5.1.7 require that boxing uses `valueOf`?

Remi Forax forax at univ-mlv.fr
Tue Mar 19 07:46:54 UTC 2024


Hello,
the JLS requires the values between -128 and 127 to be cached when boxing [1].
Byte.valueOf() or Integer.valueOf() specs [2][3] guarantee that the values between -128 and 127 are cached, and maybe more but it's okay because the JLS does not say that the values not between -128 and 127 should not be cached.

So javac can use Byte.valueOf() or Integer.valueOf() and is also free to not use Byte.valueOf() or Integer.valueOf() if the methods used cache the values between -128 and 127.

When Valhalla will land, because the definition of == on wrapper types will change, all wrapper types but java.lang.Float and java.lang.Double will respect that equivalence, x == y <=> Wrapper(x) == Wrapper(y). So the JLS 21 will still be true.

regards,
Rémi

[1] https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.1.7
[2] https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Byte.html#valueOf(byte)
[3] https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Integer.html#valueOf(int)

----- Original Message -----
> From: "some-java-user-99206970363698485155" <some-java-user-99206970363698485155 at vodafonemail.de>
> Cc: discuss at openjdk.org
> Sent: Monday, March 18, 2024 10:41:24 PM
> Subject: Re: Should JLS 5.1.7 require that boxing uses `valueOf`?

> Thanks a lot for all your answers, especially for this in-depth compiler
> and JIT view on it!
> My previous message and the subject might have diverted this discussion
> in the wrong direction: The main problem I see with the JLS section
> 5.1.7 in its current form is that it does not seem to be very useful.
> And I assumed the only way to make it useful would be to require using
> `valueOf`, but maybe there are other ways as well.
> The problem is that if you were to strictly follow the JLS, then there
> are two caching implementations:
> -"JLS cached": Implicit boxing of constant expressions in certain ranges
> (e.g. -128 to 127) to same instances
> -"valueOf cached": Guarantees provided by `valueOf`methods
> These two caching implementations can be identical (i.e. a compiler uses
> `valueOf`for boxing), but there is no guarantee for it.
> If one would now want to write a `List<Byte>`which contains 'canonical'
> boxed values they would have to write rather contrived code to be JLS
> compliant:
> -implementation using "JLS cached" values:
> ```
> void add(byte b) {
>     // Canonicalize to "JLS cached" values, which only applies for
> constants
>     Byte boxed = switch (b) {
>         0 -> (Byte) (byte) 0;
>         1 -> (Byte) (byte) 1;
>         2 -> ...
>     }
>     list.add(boxed);
> }
> ```
> -implementation using "valueOf cached" values:
> ```
> void addZero() {
>     // Must explicitly use `Byte.valueOf` even if IDEs and static code
>     // analysis tools say it can be omitted
>     Byte boxed = Byte.valueOf(0);
>     list.add(boxed);
> }
> ```
> In reality this might not matter much because most (if not all)
> compilers use `valueOf`for implicit boxing, and as you said Project
> Valhalla might render this obsolete in the future. But the current
> situation is not ideal if Java programs accidentally rely on compiler
> implementation details assuming that implicit boxing uses `valueOf`.
> (Though I am not sure how many programs really do perform identity
> checks on boxed primitived.)
> Regarding over-specifying: Of course the JLS should try to not be too
> specific. But that raises the question if that part of JLS section 5.1.7
> about boxed instance identity is useful at all.


More information about the discuss mailing list