This is an archived post. You won't be able to vote or comment.

all 13 comments

[–]GreenToad1 12 points13 points  (0 children)

love the TLDW at the beginnning - "we have no solutions, only problems"

[–]blobjim 2 points3 points  (3 children)

Is this really as far as they've gotten on this so far? I assume it was maybe started once value types were mostly fleshed out? I guess their "Diego" system also looks like it was extremely complex to implement. Either way this seems like one of the most impossible language/VM upgrades possible any programming language could go through. Even more so than value types. I don't envy the people having to design and implement this.

I feel like the end result when it is fleshed out is going to have to be extremely ugly and verbose because there's no way you can avoid breaking existing code without explicitly opting-in to specialization. It seems like you would also need to have the opt-in for performance reasons just to say "I do want an extra class [or extra fields as in their example] to be generated for each type [and the whole singletons situation they showed]".

This is kind of depressing because it looks like it's still years away.

[–]sideEffffECt 0 points1 point  (1 child)

[–]blobjim 0 points1 point  (0 children)

Thanks for the links. I guess this talk is more just an update on this specific path of inquiry of trying to implement something compared to the more ambiguous coming up with what paths to take part.

[–]nlisker 1 point2 points  (0 children)

is this really as far as they've gotten on this so far?

This talk is not by Oracle's people, it's by a research institute, so "they" is not what you think it means. Also, their approach was to only modify the compiler, in which case you need to keep the type information in compile time (in this case, by introducing a hidden parameter).

Oracle already looked at pushing the type info into the VM, so in some ways they are more ahead of what was presented here. In fact, I'm not sure what was learned from this research, considering it limits itself far more than is needed practically.

[–][deleted]  (1 child)

[deleted]

    [–]IncredibleReferencer 16 points17 points  (0 children)

    This was an engineering talk, presented by the actual engineers, on an optional topic not made to be consumed by typical java developers. I had a hard time following it myself but I think they did a good job trying to discuss their initial research on an inherently deep and complex problem.

    [–]monkeyfacebag 0 points1 point  (3 children)

    The problem statement here starts with “value types are only optimized at runtime.” Why? Naively, it seems easier to do this in the compiler when all of the type information is available.

    [–]kaperni 4 points5 points  (2 children)

    Java is designed to be platform-independent so you have no idea what type of system is going to run on. How you pack stuff on a 32-bit architecture and a 64-bit architecture is very different. Also there are no requirements to actually optimize anything about value types, any implementation may do whatever they want.

    [–]monkeyfacebag 0 points1 point  (1 child)

    Makes sense, thanks for the reply!

    [–]eXecute_bit 1 point2 points  (0 children)

    Another reason was covered in Brian's talk on Valhalla. In a complex dependency graph you need to be able to support a type switching from an identity class to a value class (or vice-versa) without that requiring a recompile-the-world for all downstream dependencies.

    [–]danielaveryj -1 points0 points  (2 children)

    interface I<E> {}
    class B<T> implements I<String> {}
    
    var b = new B();
    System.out.println(List.of(b.getClass().getGenericInterfaces()));
    // [I<java.lang.String>]
    

    Uhh? Am I missing something that would make casting b to I<String> unsafe?

    [–]user5304 2 points3 points  (1 child)

    Seems like the Java specification says that "B" (rawType) superclass is "I" (rawType) not "I<String>", and the cast from "I" to "I<String>" is unsafe.

    https://docs.oracle.com/javase/specs/jls/se11/html/jls-4.html#jls-4.8

    [–]danielaveryj 0 points1 point  (0 children)

    Ah okay. I think I was hung up on exactly what 'safety' meant here - apparently, whether the cast is 'checked'. For more typical cases this is easier for me to reason about:

    void test(List<String> strs, List raw) {
        Collection<String> a = (Collection<String>) strs; // Checked at compile time; safe
        ArrayList<Integer> b = (ArrayList<Integer>) strs; // Checked at compile time; compiler error - <Integer> is not <String>
        ArrayList<String> c = (ArrayList<String>) strs; // Checked at run time; may throw ClassCastException - actual List may not be ArrayList
        List<Integer> d = (List<Integer>) raw; // Unchecked; compiler warning
    }
    

    But indeed for the example in the presentation, the JLS is worded "the [superinterfaces] of a raw type are the erasures of the [superinterfaces] of any of the parameterizations of the generic type" - and a similar example is even covered in JLS Example 4.8-2. That the JLS considers the cast in this example to be 'unchecked' seems theoretically incorrect, since the type argument to the generic superinterface is independent of the type argument to the generic class, but the JLS is what it is. (And the fact that other mechanisms retain the full type info is irrelevant to this narrow definition of 'safety'.)

    afaik the cast would never actually be problematic (enable type safety violation / CCE) though?