
Value Type Hygiene - kjeetgill
http://cr.openjdk.java.net/~jrose/values/value-type-hygiene.html
======
niftich
What a fascinating design constraint: to retrofit a useful feature into the
Java ecosystem while keeping as many things backwards-compatible as possible.
This proposal has a much stronger answer to backward compatibility than the
previous one, by letting all ported builtin classes keep the same descriptor
in the bytecode. The catch is that each class file will now declare which of
the types it imports are ValueTypes, and which aren't.

Java's strong commitment to bytecode-level backwards-compability is sometimes
to the detriment of its feature-set (e.g. non-reifiable generic types due to
type erasure), but this commitment is a large contributor to the platform's
success.

~~~
pron
Non-reified generics is the feature that allows different JVM languages to
interoperate much more easily and share data structures. If you look at the
CLR, interop there is much messier, largely due to this. The reason is that if
reference-type generics were reified, then the JVM must know the subtyping
relationship between such different types, and different languages have very
different variance strategies. This limitation does not apply to types that
cannot be subtyped, which is why value type generics can (and will) be
reified.

In exchange, you pay with a minor nuisance: mostly the inability to overload
methods with the same erased types. I think most would agree that having a
truly polyglot VM that allows different languages to enjoy the data structures
written in other languages is much more important.

~~~
bradleyjg
It’s an interesting trade-off. It makes java a somewhat weaker language but
the jvm a better platform. At the time the decision was made, probably no one
was thinking of the jvm as polyglot platform. So there was a decision whose
chief benefit was only revealed in retrospect.

~~~
bunderbunder
It's also possibly an unnecessary trade-off.

Scala, for example, has something akin to reified generics, without any
support from the JVM itself. It also allows for a decent level of interop with
other JVM languages, though of course all you can really "export" to other
languages is the least common denominator semantics required by the JVM.

Java could theoretically do something similar: Maintain type information that
is visible to Java at compile- and run-time, while still compiling to code
that is consumable from other languages without too much hassle. Really,
personally, I only care about it being available at compile time. Haskell, for
example, erases types much more aggressively than Java does, while also
maintaining a high level of type safety.

I guess I don't know that it's backwards compatibility on the JVM that bothers
me so much as Java's tendency to think of itself as being little more than a
JVM macro assembler with C-like syntax.

~~~
pron
That's not so simple. The class file, I believe, does have the generic
instance at the _use site_ , but then if you could have two overloads,
foo(List<String>) and foo(List<Integer>), which would you call if you use a
raw type (either in Java or from other languages). It's not that Java is a JVM
macro assembler so much that there is not much to be gained from this feature
given the rest of Java, and Java has a very different design philosophy from
Scala, as it aims at a different audience. If and Java evolves in that
direction, perhaps this feature would change. In the meantime, those who like
Scala can use Scala.

~~~
bunderbunder
This feels to me more like a failure of imagination than a technical
impossibility. C#, for example, handles some things like this by exporting a
function with a special name in the compiled modules. Java could do the same -
handle the overload by having them be two different methods named something
like foo__String() and foo__Integer() on the back end. The naming may not be
beautiful, but I think that, if you do it right (for starters, try to use more
readable naming conventions than Scala does), it can make for a pretty sane
user experience for consumers who are using different languages. Naturally,
the best practice would also be to design so that the API remains clean for
packages that are meant to be consumed by multiple JVM languages.

I also want to point out that having a type system with a stronger handle on
generics is about more than just ergonomics when overloading methods. As
another example, Java's story for auto-mapping libraries
(serialization/deserialization, lighweight ORM, stuff like that) is materially
hindered by the inability to express things like "List<MyDataType>.class". And
those sorts of things do have a material impact on developer productivity -
when I'm working in Java, I find that I spend an inordinate amount of time
writing, maintaining and code reviewing all the extra glue code that needs to
be written to handle tasks that other languages make almost effortless.

~~~
pron
> This feels to me more like a failure of imagination than a technical
> impossibility.

It's not the lack of possible solutions, but more of a design philosophy.

> is materially hindered by the inability to express things like
> "List<MyDataType>.class

See Guava's TypeToken
[https://google.github.io/guava/releases/25.0-jre/api/docs/co...](https://google.github.io/guava/releases/25.0-jre/api/docs/com/google/common/reflect/TypeToken.html)

> I find that I spend an inordinate amount of time writing, maintaining and
> code reviewing all the extra glue code that needs to be written to handle
> tasks that other languages make almost effortless.

Which is why the Java ecosystem offers a nice selection of languages to match
almost everyone's taste. Many people like Java and feel productive using it,
and those who don't can enjoy the great polyglot interop afforded by, among
other things, generic type erasure.

------
willvarfar
I can't wait for Value Types to land! The contortions my code has to go
through to fit in RAM and avoid fighting the garbage collector drives me nuts.
Problems that might fit in a few megabytes in, say, C/C++ can take gigabytes
in JVM. I have always looked at the C# structs with envy.

Rah rah I hope the authors peek on HN and see that their work has baying fans
:)

~~~
pjmlp
C# has much more than only structs.

You can do manual memory management, GC free code blocks and there is unsafe.

Additionally C# 7.x has safe stack allocation, spans, references to stack
allocated data.

Looking forward to have some of those goodies in Java as well.

~~~
apta
> Additionally C# 7.x has safe stack allocation, spans, references to stack
> allocated data.

How much of those are the direct result of having value types in the language?

As far as the other features you mentioned, it would be nice to have them in
the JVM as well.

~~~
pjmlp
All of them.

They were already available in other languages like Modula-3 and Oberon(-2)
before Java came to be, but Java team decided it was too complicated for their
target audience.

Just like Sun was religiously against AOT, a feature only available in
commercial third party JDKs, they also believed it was a matter of making the
JIT good enough for escape analysis.

Thankfully the .NET team had other beliefs.

------
tom_mellior
Silly quick question: What is the "L-world" discussed here?

~~~
kjeetgill
The letter L is used in the JVM bytecode specification to refer to objects (as
opposed to primitives or arrays). You'll often see that notation when using
jmap or javap.

[https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.ht...](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.2)

~~~
tom_mellior
Thanks! I'd seen that notation before, but I didn't connect it to this
context.

------
lsd5you
Presumably I'm missing something, but are they trying to do something more
than just Boxing value types? (Specialization?) I cannot see how legacy
classes would be impacted if Boxing was used, nor quite why it is going to be
so difficult. Boxing would seem to deliver most of the benefits (i.e. the
ability to do things in a memory efficient manner in new code).

~~~
dgreensp
Yes, the point is to not box them.

~~~
lsd5you
Yes, in ArrayLists ... etc., but if you want compact values on the stack, or
compact value data structures you don't need this. I feel like 80% of the
solution (and one which is likely future compatible) is going begging whilst
they worry about nice to haves.

------
vvanders
Happy to see value types making their way, however I'd put good money on not
seeing this in Android until 2030 at the earliest.

~~~
Larrikin
In the Android world, it's quickly becoming what Kotlin supports.

~~~
sureshv
Still need JVM support of value types for this to make sense.

~~~
jayd16
Android doesn't use the JVM. Hell, it doesn't even really use a VM any more.

~~~
pjmlp
Sure it does, ART was AOT only during Android 5 and 6.

Android 7 brought the VM back.

Now it uses an interpreter hand written in Assembly that gathers PGO info for
the JIT, which also performs PGO data gathering, then only the hot bits are
AOT compiled to native code, when the device is idle.

Any change on the execution path or updates trigger the execution process from
the beginning.

~~~
wolf550e
I didn't know that. Here are the docs:
[https://source.android.com/devices/tech/dalvik/jit-
compiler](https://source.android.com/devices/tech/dalvik/jit-compiler)

~~~
pjmlp
The docs are outdated, Android P is bringing sharing of PGO data across
devices via the Play Store.

[https://www.youtube.com/watch?v=Yi9-BqUxsno](https://www.youtube.com/watch?v=Yi9-BqUxsno)

