Designing for value types

Brian Goetz brian.goetz at oracle.com
Wed Jun 6 15:24:49 UTC 2018


The JVM has (basically) five types now: int, long, float, double, and 
reference.  (All the rest can be thought of as restrictions on these 
basic ones.)  For each, the default value is the all-zero bit pattern; 
null for references, zero for numbers.  For various reasons at multiple 
layers, this is a very convenient choice (in fact, probably the only 
tenable one).  At allocation time, the Vm just gets out a big 
zero-colored paint roller and paints the whole object in one stroke 
(though this can be optimized away if the VM can prove all fields are 
explicitly written before the reference escapes). This is especially 
important when it comes to arrays.

Since values are ultimately concatenations of fields of other types, 
there's an obvious answer for the default type of values: the default 
value of a value type is one for which all of its fields have their 
default value (recurse as needed.)

This may present a burden on value type developers: the all-zero bit 
pattern _must_ be a valid value, because that's what the VM is going to 
give you from the outset.  For some classes, this is perfectly 
convenient, as in the following:

     value class Complex {
         double re, im;
     }

     value class Optional<any T> {
         boolean isPresent;
         T value;
     }

In these examples (and many others), zero is a natural default value, 
and there is no more work to do on the part of the value class.  But in 
some classes, its a pretty lousy default value.  (And in some, there's 
no good default value.)  This is where the burden falls to value 
writers.  For example, let's say you have a value that models a native 
pointer.

     value class NativeAddress {
         private long baseAddress;
         private long offset;

         int readInt() { ... }
     }

A default NativeAddress corresponds to a null pointer, so methods may 
need to be coded defensively:

         int readInt() {
             if (baseAddress == 0)
                 throw new NullPointerException();  // or more 
appropriate error
             ...
         }

Thinking about this problem for 30 seconds or so will surely bring you 
to the question "well, why not just let the value class nominate a 
default value?"  This seems obvious and cost-free -- when you think 
about it only from the perspective of writing the value class.  But this 
has some pretty big hidden costs when you think through how this might 
be implemented, and they're not just "makes life more difficult for JVM 
implementors."  So without rehashing the many many hours of discussion 
on valhalla lists here, let's just say this isn't remotely as simple or 
cheap as it looks.






On 6/6/2018 10:57 AM, Tagir Valeev wrote:
> Hello!
>
> Assuming that LocalDateTime would be a value type, which default value 
> should it have?
>
> With best regards,
> Tagir Valeev.
>
> ср, 6 июня 2018 г., 21:07 Brian Goetz <brian.goetz at oracle.com 
> <mailto:brian.goetz at oracle.com>>:
>
>     Since Java 8, several classes (Optional, LocalDateTime, etc) have
>     been
>     tagged as _valued based_:
>     https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html
>
>     This was our stake in the ground that these classes might become
>     candidates for migrating to values.  These guidelines are a pretty
>     good
>     start, but have some known holes.  Plus, its a generally good way to
>     model many things.
>
>     The biggest known gap is nullability.  Value types can't be null; not
>     only can reference types be null, but that's actually their default
>     value!  You can see the problem.  The definition of value-based says
>     nothing about null, because, well, it seems kind of silly to say
>     "value-based types shouldn't be null" when that's exactly the default
>     value the JVM places in them.
>
>     If you program with value-based classes now, and have good hygiene
>     about
>     nulls (don't leave fields uninitialized, don't store nulls in
>     them) --
>     which a lot of code does -- migrating to values should be relatively
>     painless.  We're working on lint warnings in javac to flag uses of
>     value-based classes in ways that won't migrate well to values, which
>     will help further.
>
>     If you're in a position to recompile all clients when you switch from
>     value-based classes to value types (a common situation for simple
>     domain
>     classes), and you've kept your code clean, the migration should be
>     pretty smooth.  The migration for existing types like Optional,
>     which is
>     used (and misused) from lots of existing code, is going to be a
>     longer
>     and rockier road.
>
>
>
>
>     On 6/6/2018 9:51 AM, David Lloyd wrote:
>     > There are various classes in the JDK which follow certain practices,
>     > seemingly in the hopes of being "value-ready".  These practices
>     > include things like:
>     >
>     > • No public constructors (use static factory methods instead)
>     > • Make the type `final`
>     > • No inheritance (probably? prefer composition I guess?)
>     > • No mutable state
>     >
>     > Understanding that it is still "early days" and that things can
>     still
>     > change dramatically, is it realistic to expect that classes designed
>     > to the above rules can more or less seamlessly transition to value
>     > classes in a future JDK?  Is there a definitive list of additional
>     > things an API can do to anticipate value types, minimizing the
>     > likelihood of transition problems, or is it categorically too
>     soon to
>     > tell?
>     >
>



More information about the amber-dev mailing list