Great skill of repeating the questions from audience. I dunno how many times you just get a presenter answering a question we don't know the question. Well done.
counter-skill: predicting the question from the answer unfortunately (or fortunately) you tend to get pretty good at this after enough talks. good answers also tend to include keywords from the questions
When I think Java I think I don't even want to run anything in Java because the smallest thing uses the most memory ever of all other things that I might want to run. @@renbangbprd7236
Restricting nulls is amazing! Stumbling over nulls where you didn't expect them is IMHO the most common run time error to encounter in Java. I am very much in favor of making initialization hard if it avoids null errors down the line.
As a long time Java developer and consultant im really happy with this careful approach. Cange is easy, improving something is not. This is an improvement. As the same time I hope they won't fall for the call of a small group to introduce complex concepts from other languages into Java. One of the reasons my clients/customers use Java is its accessability. So lets keep it at the current sweetspot that made Java so successful. Just powerful enough, not too complex.
It looks great. But I do hope there would be a way to enforce data flatness at JVM, at least on bytecode level if not from Java language. The thing is flat model is the way you interact with other processes and hardware, and being able to directly write to a flat buffer and read from it, without byte array parsing, is a reasonable requirement.
I wasn't aware that VM options (like defining max stack size for inlining purposes) would not flatten the data. It seems that you can achieve some degree of flatness with VM options. But the worst caveat seems to pertain to Inheritance. It seems to be that the reason most people say that the reason why flatness is hard is: "Because polymorphism requires dynamic behavior." I don't know if the people that make this argument are experts or not... but to me this excuse makes no sense. To be honest, the argument is false and very, very misguiding. > Polymorphism affects the way the outer scope sees the visitor object, but the Object's inner constitution never changes... So why is compilation treating polymorphism as if it were affecting inner constitution?? Now... If the reason is something more technical... Maybe the reason why inheritance prevents data flatness is that if ancestors' methods get inlined... the methods (maybe??) become eligible for a new JIT reordering. This may become an issue if the inner fields that it interacts with change. If this (oversight) is the true reason why, then, If the compiler could acknowledge inner mutable behavior, maybe inlines should keep memory fences (at the beginning and the end of the method) to prevent excessive reordering after inlining... maybe loads should all be treated as "opaque". It seems to me there is a technical reason people are not stating when using the excuse that "flatness is hard because of inheritance"... to me it doesn't make much sense.
@@juanandrade2998When accessing an instance field, Java needs to know where in the instance's memory that field is found. This information is uniform across all instances and so it needs to be saved only once. (If every instance could have a different memory layout, they would all need to describe it and memory consumption would go through the roof!). Imagine that instance has a `Number` field. How many bytes does that take? Easy, one pointer worth of bytes. Now imagine you want to flatten that number. How many bytes does it take to store that number? Depends whether it's a `short`, `int`, `long`, etc. right?
What I’ve been missing a lot in Java are stack-allocated and destructible tuples or unnamed records like in any other major language. Oftentimes, I don’t want an extra heap alloc for a Pair or a Tuple type, nor for a record or a class. I just want to return multiple values copied off the stack, including pointers, without an extra indirection and a cache miss. With the switch expression it would be a bliss now. It’s great how C# lets you control this via stackalloc and Spans. Any chance we can have such a tuple expression on top of a value record perhaps?
Tuple expressions as you describe them are defined by their structure, which is why they are also called "structural types". Java prefers "nominal types", i.e. types that are defined and distinguished by their name. As such, I don't see ad-hoc tuples in Java's future, but once value types land, you can easily create a domain-specific type for a multiple return scenario with a line like `value record UserWithOrder(User user, Order order){ }`. The addition of `value` means the runtime doesn't have to track the type's identity, which makes it much more likely that it will be scalarized on the stack, this getting you what you want.
@ Well, Scala, Kotlin, and C# have somehow long managed to provide that, though also nominally typed. I’m not asking for a general-purpose structural typing semantics. I’m asking for the variadic free product type S x T x U x … as a value type. Nothing more. I can already define use-case based named product types as reference types. And in Java this mandates an extra class file. Now suppose I have varying products. Or suppose I need just an ad hoc fold/reduce expression. Why would I give each such class a name?
@@Markus_included It will not optimize for this requirement. Java stack allocation works only for flat objects with references which do not escape body of method.
@@Nick-yd3rc I want to give most such classes a name, so the code remains readable. "method().user()` is eminently more readable than `method().first()`. But if you want general-use tuple types, nothing is keeping you from creating them. And once JEP 401 lands, they're unlikely to cause heap allocations.
I proper comparison is with .NET Core; .NET C# is Windows-specific, of course, it's easier to impleement every fancy feature, when you don't support a real platform language. Then came .NET Core, realizing being a platform and getting further away from Windows is a good thing, because... you know... Linux servers. DotNet languages also dump lots of features into the language, and I don't feel it nice still. Like LINQ. Feature-creep is not good by itself. Java takes a more safe approach, and maintains serious backwards-compatibility. C# didn't do that. Serious differences. Of course C# is better. In some aspects. Java's simplicity, however, is also its advantage. There is much less magic in Java compares to C#, and magic is not good, however fancy it looks on first glance.
While at it, this must be the occasion for value classes to have record-like constructor syntax. `value class Complex(double re, double in) {}` If possible, apply it to regular classes and enums too.
value classes can have private fields, records cannot, so it doesn't make sense to use records syntax. But don't worry, if you need to, you can have a value record to use both features. If you want more informations you can search "are-java-records-intended-to-eventually-become-value-types" on stack overflow. (I would send the link if youtube allowed me to)
@ only record syntax but not record behavior. It’s purely for construction. Record is designed as that because it’s transparent data carrier so regular classes and others could have a different one.
@@kienha9036 but we know that the purpose of records are to transparently carry the data. For sure value classes won’t be like that, otherwise, what’s the use of having both.
@@julianjupiter5890 no. Record is semantically enforced class that is suitable as data carrier. From the language point of view, the way you use them does not matter. Value class is instruction for the runtime about the memory layout, it has nothing to do with intended usage nor any implication carried by record. In fact, data carrier class is more suitable as value class, which is closer to struct, than record, which still carry polymorphism capability. If you think your suggestion is worthwhile and applicable, you should direct it to amber-dev mailing list.
"The most promising approach so far builds on something akin to type classes in Haskell" - omg what is happening! So will operator overloading be accomplished by implementing some standard interfaces (eg, PointAddition implements Plus)? Good to see Java is borrowing from a lot of functional concepts.
Very interesting. The choices made long ago might be bad in hindsight, but understandible. Quite hard to think of solutions that are superior but backward compatible. To me the ‘value’ keyword simply means ‘immutable’ but they probably could’t/wouldn’t use that as it overlaps with the ‘final’ keyword. And I suppose a value classes can not contain non value-class fields.
Regarding nulls in 64-bit ints, I wonder if any runtime used Long.MIN_VALUE to store the null state. That would mean integer underflow & overflow would produce a null value, which is kind of odd, but not presently correct either. It would allow abs() and negate() to always work because the size of the positive and negative integers would be the same.
Valhalla's goal of "having any form of control over memory layout of your application" is like that awesome Steam game that has been on Early access for like 10 years and every once in a while devs give some sort of statement that its definitely going to be released quite soon. I have a little bit of experience writing compilers and I don't understand how it could take this long to release one of the biggest performance enhancement since the inception of JIT! From my observation, Java(javac) has been evolving quite fast, JVM on the other hand seems to be a bottleneck. It seems the more implementing a feature is connected to JVM(HotSpot), the longer that feature takes to implement.
You're not wrong, changes to the JVM are among the most complex in OpenJDK and thus tend to draw out feature development. I think Brian once said that JVM developments is ~10x as intensive as language development (but don't quote me on that). Given that the runtime has to implement all of Java's lofty promises (i.e. the specifications) plus all real-world requirements (particularly regarding performance, but also extensibility, observability, etc) that's not too surprising - it's a complex beast solves complex theoretical and practical problems.
@ yeah You’re right. I guess that’s unfortunately something intentional to do from the very start at the type system level. But hope this to become the direction that should be taken at some point. Either way, I recently found some pattern that links Java current projects together with some blank spot to fill. So to speak, Java with all the sprinkle features that’s been added recently is moving it towards platform language instead of programming language as of today. So Java’s endgame as platform language is : ⇒ ⬙ Project Valhalla (immutable semantic type system - colourless data) ⇒ ⬖ Project ??? (algebraic effect and effect handler - colourless action/behaviour/function) ⇒ ⬘ Project Leyden (Idempotent and Incremental build on top of Idempotent and Incremental compilation - colourless build) ⇒ ⬗ Project Loom (synchronous performance - colourless performance)
Explicit non-null types via "!" is a bad idea. It should be a default option instead, because you would need to type it everywere from now on. I would opt for what Kotlin did and create some unknown-nullability types, or platform types like they call it there, for all libraries compiled in earlier Java versions. Another thing is that initializing primitives to default values was a big mistake in my opinion. Probably if non-null types existed from the very beginning this problem would be solved eons ago and it wouldn't come back now. I imagine also that introduction of value types will instease a usage of "==" operator and related to it bugs with using it when comparing objects. That could also be potentially addressed in some way or another to unify it to always make it compare by structural equality instead of identity. Lastly, one thing that was ommited from this presentation was a subject of reified generics. Would that be implemented in some way in Valhalla?
Very interesting. One thing I would disagree with is that zero is a good default for numeric types. Often it is, and we are used to it being the case, but there are many cases where zero makes as much sense as a default date of 1 Jan 1970. Eg height, weight - basically for anything measured rather than counted, zero is a bad default. Nullable value types in C# are very useful for representing values which we don't know, and the value type math i.e. 1 + unknown = unknown is useful as well.
Zero isn't a good default because it naturally occurs (which isn't the case for the measurements you give as examples) but because of its mathematical properties as the neutral element of addition (which still applies). But as Brian explained and you expanded with your examples, no matter how good of a default it is across the board, unless it's *always* (or at least very nearly always) a good one, we need a way to handle the other cases.
I don't think they will be added. Their benefit is that they can avoid naming collisions but since there are other ways to work around those, all that remains is basically a way to obfuscate code by reducing local readability, a property that the Java architects are known for valuing.
What I don’t like about the syntax for “value classes” as proposed is that one has grown accustomed to associate the new keyword with a heap allocation. One can construe the “implicitly stackalloc” new semantics as a bonus of course. But I think more verbosity wouldn’t hurt here. Also, a Span like semantics would be nice to have out of the box, like in C#. In addition, I believe I said that a couple times before, I can’t wrap my head around the naming deviation, why not just call it a “struct” and a “struct record” instead? That’s what many other languages call value classes.
That's the thing I like about Java, you don't need to think a lot about the memory semantics of your code, you just feed your bytecode to the JVM and it will do those optimizations for you
@ erm, no it won’t in many cases, and it won’t do this reliably. This is the reason why the runtime is nondeterministic. The .NET CLR is quite similar to HotSpot, but you can opt into more control. Brian covers that idea with “finals” and other keywords. A “value” class qualifier is similar. By your argument, you wouldn’t need either, the JVM should figure this all out for you. But that’s not how you get the performance that you want and can have given the constraints known to you at compile time. I believe whether you’re content with what HotSpot does depends on what you’re working on. I do need to think about my memory semantics a lot. All modern compilers are optimizing and runtime optimizations render them nondeterministic. For low latency workloads, it’s material to reduce the degrees of freedom and assist the compiler with all the information that you have regarding your runtime data semantics. JIT and AOT don’t solve the problem and aren’t smarter than you if you know exactly what you need. The notion that depending on the PGO and other circumstances, HotSpot would forgo a heap allocation and do a stackalloc instead when it deems it reasonable, results in only stochastic guarantees for the run-time behavior of your system. But if you mostly do Spring Boot business apps, then sure, one wouldn’t need to care as much about that, just scale up.
One thing in java that really bugs me is how you haveto use .size() for some objects and .length() for others. Its so inconsistent. People give C++ a lot of crap, but at least its consistent on this point.
One is for arrays and its a property, not a method. The other is a method on the Collection interface. I generally agree but its luckily easy to remember that array uses the length property and anything else is size method.
@alexandersagen3753 yeah I know it's not hard to remember. I couldn't because apart from a little bit a few weeks ago I haven't written anything in Java for a long time. I do actually like Java, but this one thing (and also the whole thing mentioned in the video where you can't use something like "int" with an ArrayList) really annoy me. 😅
I love finding videos like this and playing the "# of comments before a Rust user shows up". This was the firs today I didn't see a single Rust programmer complaining.
Congratulations on adding things that C# has had since 1.0. And maybe even proper generics like C# 2.0. The current generics implementation in Java really seems like what it is, tacked on rather than peroperly integrated, because the runtime has no idea that generics exist.
Java's approach is called 'Type Erasure' while C# uses 'Reified Generics'; it's intentionall, different on the runtime level. Comparing Java to C# does not make justice, C# was Windows only. That's the whole point of C#: Java refused to integrate with Windows deeper and kept its platform approach, so Microsoft had to write their own Java more closely implemented for Windows. Hence C# was born. A proper comparison would be Java vs. DotNet Core, which is basicslly C# re-implemented (with reduced feature-set) to be a platform language, like Java.
I've returned to Java after a 20 year hiatus. It is greater than ever. Loving Records, virtual threads, lambda expressions, pattern matching, and the GRAAL VM. But I couldn't care less about the new "var" statement. Not necessary. The whining I read about too much boiler plate code is silly. Today's IDEs have awesome code completion features. Instead a genuine improvement would be to make curly braces, semi-colons, and () in if statements optional like Scala has done.
Agreed on var. There are times when it's nice, like when I have crazy data structures like a map or lists or whatever. Generally though, I don't use it. Out of curiosity, what other languages were you using in your 20 year absence?
@@nojerome497 I became a Drupal web developer which uses PHP. I've become very good at it. The Drupal API isn't the easiest thing in the world to master. Also, I of course use Javascript. Where I work the backend is a very large and very old CLI system written in TCL. We've just started to convert it to Java. The web apps will remain in PHP for now.
I find that if the code becomes hard to read after refactoring it to use var, it means that either the variable names are not descriptive enough, or the method is too long. Or both. Having said that, this is certainly an optional feature that you do not have to use. Each team just needs to agree on their approach.
My biggest complaints with Java don't involve its internals, grammar / syntax and operational model. They involve the evolution of the thousands of libraries over nearly 30 years with no obvious guidelines used to impose semantic naming conventions so the intent and proper use of the libraries can be readily understood by a new user of that library. Example: some Spring Libraries distinguish between reactive and non-reactive methods by embedding Reactive in the name like this --> InMemoryReactiveClientRegistrationRepository. But other parts of the same libraries use the word Server instead. The combination of extremely long class names consisting of generic words used routinely in software with inconsistent semantics makes the code written with them visually hard to read, nearly impossible to learn from by looking at examples and generates a flood of imprecise questions about their use online with equally imprecise answers. This is turning "the language" into a Tower of Babble."
We can't even agree on what character we use for indentation or how to place curly braces but you think we could agree on a semantic naming convention that encompasses fields like medicine, law, finance, and logistics as well as language norms from Europe, the Middle East, Eastern Asia, and the rest of the world? And developers would follow it? Some don't even care to learn about punctuation!
As the first example that came to mind, I checked the C# spec. It says: "Structs are value types (§8.3) and are said to have value semantics. Classes, on the other hand, are reference types (§8.2) and are said to have reference semantics. A variable of a struct type directly contains the data of the struct, whereas a variable of a class type contains a reference to an object that contains the data." After watching the talk, you know that the last paragraph does not apply to Java's value types, so calling them structs would be very confusing. It would lean on a widely known term but with subtly different semantics. Also, unlike the C# spec, I would find it weird to call numerical primitives like `float` structs.
"beautiful objects": it feels strange to me by now to refer to an object as beautiful. in reality working with codebases full of abstractions is a late price you pay for not doing it functionally.
Because that doesn't help the millions of people and thousands of companies who have invested time and money into their Java knowledge and projects. Creating a new language is easy, porting existing projects to it is mostly a waste of resources. So these people and organisations are better supported by improving Java than by offering them an alternative. (And that's leaving aside that there's basically no alternative that is as battle-tested and comes with as rich an ecosystem like Java does.)
This is the answer: CASH - people who use java would lose jobs, so they have an invested reason to push the dying cart down the road. I remember when java was a buzzword and the government was passing out contracts just based on the fact that if you ran Java, then your opportunity award amount would go up exponentially -- it was a good way to increase your ask from the govt. There were bureaucracies, audits, and other corporate/govt greedy corruption in place to floss more money. Java is/was a poor choice from the beginning. -- I used to work on the Java source code at red hat and that local college that they were in tandem with. My history with java ensured that I never work with java after 2001. I handled bare-metal problems and I knew java was/is a death trap (for any company seeking independent productivity). Its the perfect corporate greed programming language. I would compile the JVM and find bugs and try to fix major memory problems, they'd stall refactoring. They would literally tell me to hide or mask stuff. Anyway, I stayed far away from it (unless I had to code android or oracle). Its a very bad choice for new projects (and it was bad back in the day, but the cheerleader section out screamed the guys that had their ear to the track and knew better). Today, C#, Python, Rust, C, and C++ is your choice for opportunities. I still keep up with Java because I had such a deep dive in my early student days and career days. I know more about Java than maybe 90% of most java programmers and I won't use it for any corporate or enterprise solutions. Java requires way too much god level wisdom to make it work correctly (and James Gosling did that on purpose (for Sun (for customer retention))). I one time I forked and created my own version of JVM and the java compiler just to fix the problems with Java. I decided to make my own custom language for my own company. But I am thankful for Java. Java made me aware in my youth that the (corporate^^govt) world does not care about productivity and most of the corporate jobs are just seats beholden by very untalented minds that want a cushy job where the C-Suite guys can't question your knowledge. Its all about CASH and job security in the enterprise^^corporate^^[ corrupted govt ] worlds based on obfuscated information. This presentation was exactly how I expected this "refactor" to go: nothing burger.
Alternatives are already there. Namely, Kotlin, without the porting issue, since it's interopable with Java. I might be wrong, but in my reading Kotlin contains most of what Java 2 could be. Since a few versions, Java started to add new concepts, e.g. record types, but it's fairly easy to adopt them into Kotlin and extend it instead of making something yet again from zero with not much advantage. Reified generics are still missing, from Kotlin too, but that's a JVM limitation. And as presented, they upgrade the JVM; so I hope reified generics will arrive at some point, or some unification at least, as in Kotlin (no int vs. Integer anywhere, just Int) and make it fully optimized.
I don't think. It's not only the Java language, it's the JRE itself, the JVM. Meaning, all JVM-based languages can benefit from these changes, like Kotlin, which is awesome!
Java widely introduced the usage of VM (tho it existed before, e.g. SmallTalk), with C-like syntax, simple concepts and complete memory-safety. And mostly sensible names, unlike C++ acronym hell. It undeniably was a big deal and by no accident it took over the software industry. Just because Java's hair turned white and there are cool kid languages around, does not mean it was a mistake. It made compromizes, yes, and I don't like them now, as many Java devs don't, but it was a great tool for a very long time, and admittedly still a fairly nice language. I myself praise Kotlin as my favorite pick. Such a productive language, I love it. But Java has due reppect to its name, making garbage collection a common thing, runtime class loading a relatively simple thing, and overall, software development simple. Give it what is due. Could have done better? I guess, as with everything. But was Java a plague? I don't believe so. Why would you say that?
There is too much historical baggage with Java, and its evolution is too slow to keep up with other technology stacks. It can only be used as a textbook for learning and archaeology.
And yet, Java's virtual threads are an industry leading concurrency programming model (better than callbacks, async/await, and reactive) and not many languages have the same level of pattern matching support that Java has (and will get with future developments in that area). Just to name two recent developments that disprove "too slow".
@ Java has many good parts too. With Rust, borrow checker is an advantage with tradeoffs. Java style OOP then again is much more clearly just a problem with no particular tradeoffs.
@gJonii Yeah, but it's so integral to the philosophy of Java. If you think that this is bad (for probably good reasons), you should use a different language.
I wonder if bytecode could get the "String bang" kind-of syntax, while the language would have a backwards-incompatible change with the questionmark making types nullable; so JARs (bytecode of older versions) still usable as before, only that new source code must add the question mark for explicit nullability. C# did something similar, and C# has a big ecosystem too. If they add this nullability restriction onto the type definitons themselves... it sounds like a little help, but null should be in the type system, properly. Asking for union types (so T|null) is likely too much, but as in C#, or rather, Kotlin, T? would be so much nicer, to define nullability at each usage. If indeed nullability will be a flag on the types, I will definitely look at it as a step in the wrong direction. I guess it's backwards-compatible, and hence is chosen. But doesn't feel right.
Great skill of repeating the questions from audience. I dunno how many times you just get a presenter answering a question we don't know the question. Well done.
Exactly. Clearly an experienced presenter.
Most of the Java team do this.
Bring the low memory usage, I hope lilliput+leyden+valhalla can reduce java memory usage by ~50%
counter-skill: predicting the question from the answer
unfortunately (or fortunately) you tend to get pretty good at this after enough talks. good answers also tend to include keywords from the questions
When I think Java I think I don't even want to run anything in Java because the smallest thing uses the most memory ever of all other things that I might want to run. @@renbangbprd7236
Restricting nulls is amazing! Stumbling over nulls where you didn't expect them is IMHO the most common run time error to encounter in Java. I am very much in favor of making initialization hard if it avoids null errors down the line.
All stuff I've wanted in Java from early on. I'm all on board.
Excellent planning breaking it up into smaller features.
Your process of evolving the Java language over the years is impressive!
Never been so excited for a refactor 😂 Go team Valhalla!!
The only refactor that product managers see the business value in it :D
@@TBadalovI mean, they’re called _value_ types, what’s not to love :P
@@redpepper74 good one :D
As a long time Java developer and consultant im really happy with this careful approach. Cange is easy, improving something is not. This is an improvement.
As the same time I hope they won't fall for the call of a small group to introduce complex concepts from other languages into Java. One of the reasons my clients/customers use Java is its accessability. So lets keep it at the current sweetspot that made Java so successful. Just powerful enough, not too complex.
They have being doing that for at least 10 years.
finally oracle picking up some backlogs, nice!
Nice. "I feel dirty when I use Integer instead of int"
It looks great. But I do hope there would be a way to enforce data flatness at JVM, at least on bytecode level if not from Java language. The thing is flat model is the way you interact with other processes and hardware, and being able to directly write to a flat buffer and read from it, without byte array parsing, is a reasonable requirement.
I wasn't aware that VM options (like defining max stack size for inlining purposes) would not flatten the data.
It seems that you can achieve some degree of flatness with VM options.
But the worst caveat seems to pertain to Inheritance.
It seems to be that the reason most people say that the reason why flatness is hard is:
"Because polymorphism requires dynamic behavior."
I don't know if the people that make this argument are experts or not... but to me this excuse makes no sense.
To be honest, the argument is false and very, very misguiding.
> Polymorphism affects the way the outer scope sees the visitor object, but the Object's inner constitution never changes...
So why is compilation treating polymorphism as if it were affecting inner constitution??
Now... If the reason is something more technical...
Maybe the reason why inheritance prevents data flatness is that if ancestors' methods get inlined... the methods (maybe??) become eligible for a new JIT reordering.
This may become an issue if the inner fields that it interacts with change.
If this (oversight) is the true reason why, then, If the compiler could acknowledge inner mutable behavior, maybe inlines should keep memory fences (at the beginning and the end of the method) to prevent excessive reordering after inlining... maybe loads should all be treated as "opaque".
It seems to me there is a technical reason people are not stating when using the excuse that "flatness is hard because of inheritance"...
to me it doesn't make much sense.
@@juanandrade2998When accessing an instance field, Java needs to know where in the instance's memory that field is found. This information is uniform across all instances and so it needs to be saved only once. (If every instance could have a different memory layout, they would all need to describe it and memory consumption would go through the roof!).
Imagine that instance has a `Number` field. How many bytes does that take? Easy, one pointer worth of bytes.
Now imagine you want to flatten that number. How many bytes does it take to store that number? Depends whether it's a `short`, `int`, `long`, etc. right?
you discovered the backlog screen, great!
That is when academic-level knowledge meets industry-level (enterprise-level) technology, the result is a well-thought rigorous outcome
I haven’t written a line of Java code in 18 years but still found this interesting and understandable.
Glad to see progress is continuing.
Breaking: Java team discovers data-oriented programming
You're 10 years late. They already started planning about it back then.
16:50 I remember having the same reaction when realizing the nuance of .equals and = equality for Integer 😂
What I’ve been missing a lot in Java are stack-allocated and destructible tuples or unnamed records like in any other major language. Oftentimes, I don’t want an extra heap alloc for a Pair or a Tuple type, nor for a record or a class. I just want to return multiple values copied off the stack, including pointers, without an extra indirection and a cache miss. With the switch expression it would be a bliss now. It’s great how C# lets you control this via stackalloc and Spans. Any chance we can have such a tuple expression on top of a value record perhaps?
JVM's JIT is somewhat good at inlining code and optimizing heap allocs away, so it's less of a problem than you think.
Tuple expressions as you describe them are defined by their structure, which is why they are also called "structural types". Java prefers "nominal types", i.e. types that are defined and distinguished by their name. As such, I don't see ad-hoc tuples in Java's future, but once value types land, you can easily create a domain-specific type for a multiple return scenario with a line like `value record UserWithOrder(User user, Order order){ }`. The addition of `value` means the runtime doesn't have to track the type's identity, which makes it much more likely that it will be scalarized on the stack, this getting you what you want.
@ Well, Scala, Kotlin, and C# have somehow long managed to provide that, though also nominally typed. I’m not asking for a general-purpose structural typing semantics. I’m asking for the variadic free product type S x T x U x … as a value type. Nothing more. I can already define use-case based named product types as reference types. And in Java this mandates an extra class file. Now suppose I have varying products. Or suppose I need just an ad hoc fold/reduce expression. Why would I give each such class a name?
@@Markus_included It will not optimize for this requirement. Java stack allocation works only for flat objects with references which do not escape body of method.
@@Nick-yd3rc I want to give most such classes a name, so the code remains readable. "method().user()` is eminently more readable than `method().first()`.
But if you want general-use tuple types, nothing is keeping you from creating them. And once JEP 401 lands, they're unlikely to cause heap allocations.
New background color of Java Logo❤
Let’s go! ❤
We are so back!
Congratulations on catching up to C# 10 years ago
20 even
I proper comparison is with .NET Core; .NET C# is Windows-specific, of course, it's easier to impleement every fancy feature, when you don't support a real platform language. Then came .NET Core, realizing being a platform and getting further away from Windows is a good thing, because... you know... Linux servers. DotNet languages also dump lots of features into the language, and I don't feel it nice still. Like LINQ. Feature-creep is not good by itself. Java takes a more safe approach, and maintains serious backwards-compatibility. C# didn't do that. Serious differences. Of course C# is better. In some aspects. Java's simplicity, however, is also its advantage. There is much less magic in Java compares to C#, and magic is not good, however fancy it looks on first glance.
While at it, this must be the occasion for value classes to have record-like constructor syntax.
`value class Complex(double re, double in) {}`
If possible, apply it to regular classes and enums too.
value classes can have private fields, records cannot, so it doesn't make sense to use records syntax. But don't worry, if you need to, you can have a value record to use both features. If you want more informations you can search "are-java-records-intended-to-eventually-become-value-types" on stack overflow. (I would send the link if youtube allowed me to)
@ only record syntax but not record behavior. It’s purely for construction. Record is designed as that because it’s transparent data carrier so regular classes and others could have a different one.
Record could also become value class. I'm pretty sure thats considered. public value record A is the syntax.
@@kienha9036 but we know that the purpose of records are to transparently carry the data. For sure value classes won’t be like that, otherwise, what’s the use of having both.
@@julianjupiter5890 no. Record is semantically enforced class that is suitable as data carrier. From the language point of view, the way you use them does not matter. Value class is instruction for the runtime about the memory layout, it has nothing to do with intended usage nor any implication carried by record. In fact, data carrier class is more suitable as value class, which is closer to struct, than record, which still carry polymorphism capability.
If you think your suggestion is worthwhile and applicable, you should direct it to amber-dev mailing list.
"The most promising approach so far builds on something akin to type classes in Haskell" - omg what is happening! So will operator overloading be accomplished by implementing some standard interfaces (eg, PointAddition implements Plus)? Good to see Java is borrowing from a lot of functional concepts.
Very interesting. The choices made long ago might be bad in hindsight, but understandible. Quite hard to think of solutions that are superior but backward compatible. To me the ‘value’ keyword simply means ‘immutable’ but they probably could’t/wouldn’t use that as it overlaps with the ‘final’ keyword. And I suppose a value classes can not contain non value-class fields.
Have we come full circle, then? C# was a clone of Java. Now Valhalla will (gods willing) be a clone of C#.
Exactly what I was thinking
Nope. Java remains and will remain a much simpler language.
There's nothing wrong about being more low-level. Structs are not anything new
does it have reified generics?
Regarding nulls in 64-bit ints, I wonder if any runtime used Long.MIN_VALUE to store the null state. That would mean integer underflow & overflow would produce a null value, which is kind of odd, but not presently correct either. It would allow abs() and negate() to always work because the size of the positive and negative integers would be the same.
Yes, but imagine how slow would basic arithmetic become. Every time you decrement an int, you have to check if it would become null.
Valhalla's goal of "having any form of control over memory layout of your application" is like that awesome Steam game that has been on Early access for like 10 years and every once in a while devs give some sort of statement that its definitely going to be released quite soon.
I have a little bit of experience writing compilers and I don't understand how it could take this long to release one of the biggest performance enhancement since the inception of JIT!
From my observation, Java(javac) has been evolving quite fast, JVM on the other hand seems to be a bottleneck. It seems the more implementing a feature is connected to JVM(HotSpot), the longer that feature takes to implement.
Maybe this helps with understanding why it takes this long: th-cam.com/video/u08hjp6PF-Q/w-d-xo.htmlsi=-kOiv1aUwltHGb6b
You're not wrong, changes to the JVM are among the most complex in OpenJDK and thus tend to draw out feature development. I think Brian once said that JVM developments is ~10x as intensive as language development (but don't quote me on that). Given that the runtime has to implement all of Java's lofty promises (i.e. the specifications) plus all real-world requirements (particularly regarding performance, but also extensibility, observability, etc) that's not too surprising - it's a complex beast solves complex theoretical and practical problems.
Is the 'semantics' section referring to things like C# `Span`?
More specifically ref struct
Why nullable classes are not sum type (sealed interface) of something NULL like a placeholder interface that does nothing and the actual class ?
Because then `String` no longer includes `null`, which would be a gigantic backwards incompatibility.
@ yeah You’re right. I guess that’s unfortunately something intentional to do from the very start at the type system level. But hope this to become the direction that should be taken at some point. Either way, I recently found some pattern that links Java current projects together with some blank spot to fill.
So to speak, Java with all the sprinkle features that’s been added recently is moving it towards platform language instead of programming language as of today.
So Java’s endgame as platform language is :
⇒ ⬙ Project Valhalla (immutable semantic type system - colourless data)
⇒ ⬖ Project ??? (algebraic effect and effect handler - colourless action/behaviour/function)
⇒ ⬘ Project Leyden (Idempotent and Incremental build on top of Idempotent and Incremental compilation - colourless build)
⇒ ⬗ Project Loom (synchronous performance - colourless performance)
A simplified presentation of difficult thing, Huge respect to Brain Goetz
Looking forward to the Valhalla music video from Nanowar of Steel, featuring Brian as guest star!
Explicit non-null types via "!" is a bad idea. It should be a default option instead, because you would need to type it everywere from now on. I would opt for what Kotlin did and create some unknown-nullability types, or platform types like they call it there, for all libraries compiled in earlier Java versions.
Another thing is that initializing primitives to default values was a big mistake in my opinion. Probably if non-null types existed from the very beginning this problem would be solved eons ago and it wouldn't come back now.
I imagine also that introduction of value types will instease a usage of "==" operator and related to it bugs with using it when comparing objects. That could also be potentially addressed in some way or another to unify it to always make it compare by structural equality instead of identity.
Lastly, one thing that was ommited from this presentation was a subject of reified generics. Would that be implemented in some way in Valhalla?
Yeah, reified generics is a quite important aspect, it surprises me they did not mention it at all :(
Very interesting. One thing I would disagree with is that zero is a good default for numeric types. Often it is, and we are used to it being the case, but there are many cases where zero makes as much sense as a default date of 1 Jan 1970. Eg height, weight - basically for anything measured rather than counted, zero is a bad default. Nullable value types in C# are very useful for representing values which we don't know, and the value type math i.e. 1 + unknown = unknown is useful as well.
Zero isn't a good default because it naturally occurs (which isn't the case for the measurements you give as examples) but because of its mathematical properties as the neutral element of addition (which still applies). But as Brian explained and you expanded with your examples, no matter how good of a default it is across the board, unless it's *always* (or at least very nearly always) a good one, we need a way to handle the other cases.
Good to see some C# features here.
Yeah like the FAIL of async/await.
@@danhoward7697 what's wrong with async/await?
Nice, but import alias is still missing.
I don't think they will be added. Their benefit is that they can avoid naming collisions but since there are other ways to work around those, all that remains is basically a way to obfuscate code by reducing local readability, a property that the Java architects are known for valuing.
What I don’t like about the syntax for “value classes” as proposed is that one has grown accustomed to associate the new keyword with a heap allocation. One can construe the “implicitly stackalloc” new semantics as a bonus of course. But I think more verbosity wouldn’t hurt here. Also, a Span like semantics would be nice to have out of the box, like in C#.
In addition, I believe I said that a couple times before, I can’t wrap my head around the naming deviation, why not just call it a “struct” and a “struct record” instead? That’s what many other languages call value classes.
That's the thing I like about Java, you don't need to think a lot about the memory semantics of your code, you just feed your bytecode to the JVM and it will do those optimizations for you
@ erm, no it won’t in many cases, and it won’t do this reliably. This is the reason why the runtime is nondeterministic. The .NET CLR is quite similar to HotSpot, but you can opt into more control. Brian covers that idea with “finals” and other keywords. A “value” class qualifier is similar. By your argument, you wouldn’t need either, the JVM should figure this all out for you. But that’s not how you get the performance that you want and can have given the constraints known to you at compile time.
I believe whether you’re content with what HotSpot does depends on what you’re working on. I do need to think about my memory semantics a lot. All modern compilers are optimizing and runtime optimizations render them nondeterministic. For low latency workloads, it’s material to reduce the degrees of freedom and assist the compiler with all the information that you have regarding your runtime data semantics. JIT and AOT don’t solve the problem and aren’t smarter than you if you know exactly what you need. The notion that depending on the PGO and other circumstances, HotSpot would forgo a heap allocation and do a stackalloc instead when it deems it reasonable, results in only stochastic guarantees for the run-time behavior of your system.
But if you mostly do Spring Boot business apps, then sure, one wouldn’t need to care as much about that, just scale up.
This was great.
One thing in java that really bugs me is how you haveto use .size() for some objects and .length() for others. Its so inconsistent. People give C++ a lot of crap, but at least its consistent on this point.
One is for arrays and its a property, not a method. The other is a method on the Collection interface.
I generally agree but its luckily easy to remember that array uses the length property and anything else is size method.
@alexandersagen3753 yeah I know it's not hard to remember. I couldn't because apart from a little bit a few weeks ago I haven't written anything in Java for a long time.
I do actually like Java, but this one thing (and also the whole thing mentioned in the video where you can't use something like "int" with an ArrayList) really annoy me. 😅
I've already had Kotlin people tell me Java's nullability restrictions will be wrong and didn't have a good argument as to why.
Backward compatibility is why!
@@JoeMwangi the conclusion is that you can't fix stupid
most languages call it a struct (valuetype) versus a class (reference type). How is that new to you?
I love finding videos like this and playing the "# of comments before a Rust user shows up". This was the firs today I didn't see a single Rust programmer complaining.
It's just as common that we see people like you complaining about Rust users.
Why the value keyword was not placed in front of a class member or a method parameter instead ?
What would it do there? How would a `private final value ArrayList users;` be different from the same declaration without `user`?
It will instruct the compiler to not allocate here by reference.
Bring the low memory usage, I hope lilliput+leyden+valhalla can reduce java memory usage by ~50%
Congratulations on adding things that C# has had since 1.0. And maybe even proper generics like C# 2.0. The current generics implementation in Java really seems like what it is, tacked on rather than peroperly integrated, because the runtime has no idea that generics exist.
Java's approach is called 'Type Erasure' while C# uses 'Reified Generics'; it's intentionall, different on the runtime level.
Comparing Java to C# does not make justice, C# was Windows only. That's the whole point of C#: Java refused to integrate with Windows deeper and kept its platform approach, so Microsoft had to write their own Java more closely implemented for Windows. Hence C# was born. A proper comparison would be Java vs. DotNet Core, which is basicslly C# re-implemented (with reduced feature-set) to be a platform language, like Java.
Complex language is only adding pain to already ever growing complexity in software we're all building.
so all languages as they evolve turn into Perl 5 :)
For value classes, the id keyword would make sense
very nice talk, I would have preferred some better slides other than with just text which are hard to read listening to the speech
I've returned to Java after a 20 year hiatus. It is greater than ever. Loving Records, virtual threads, lambda expressions, pattern matching, and the GRAAL VM. But I couldn't care less about the new "var" statement. Not necessary. The whining I read about too much boiler plate code is silly. Today's IDEs have awesome code completion features. Instead a genuine improvement would be to make curly braces, semi-colons, and () in if statements optional like Scala has done.
Agreed on var. There are times when it's nice, like when I have crazy data structures like a map or lists or whatever. Generally though, I don't use it.
Out of curiosity, what other languages were you using in your 20 year absence?
@@nojerome497 I became a Drupal web developer which uses PHP. I've become very good at it. The Drupal API isn't the easiest thing in the world to master. Also, I of course use Javascript. Where I work the backend is a very large and very old CLI system written in TCL. We've just started to convert it to Java. The web apps will remain in PHP for now.
I find that if the code becomes hard to read after refactoring it to use var, it means that either the variable names are not descriptive enough, or the method is too long. Or both.
Having said that, this is certainly an optional feature that you do not have to use. Each team just needs to agree on their approach.
If anyone seeing this, please create a HarfBuzz java port. Please 😢
About the vlaue classes.. Its sad that this wasnt introduced with records. It would make sense if they were value by default
10 years? something went terribly wrong
My biggest complaints with Java don't involve its internals, grammar / syntax and operational model. They involve the evolution of the thousands of libraries over nearly 30 years with no obvious guidelines used to impose semantic naming conventions so the intent and proper use of the libraries can be readily understood by a new user of that library. Example: some Spring Libraries distinguish between reactive and non-reactive methods by embedding Reactive in the name like this --> InMemoryReactiveClientRegistrationRepository. But other parts of the same libraries use the word Server instead. The combination of extremely long class names consisting of generic words used routinely in software with inconsistent semantics makes the code written with them visually hard to read, nearly impossible to learn from by looking at examples and generates a flood of imprecise questions about their use online with equally imprecise answers. This is turning "the language" into a Tower of Babble."
We can't even agree on what character we use for indentation or how to place curly braces but you think we could agree on a semantic naming convention that encompasses fields like medicine, law, finance, and logistics as well as language norms from Europe, the Middle East, Eastern Asia, and the rest of the world? And developers would follow it? Some don't even care to learn about punctuation!
I got one thing to say about this, PYTHON.
So... Java finally bends the knee to the power of C structures... Why not just call them "structs" - like C# does?
Because they are immutable.
Or you could call it struct like other languages.
As the first example that came to mind, I checked the C# spec. It says:
"Structs are value types (§8.3) and are said to have value semantics. Classes, on the other hand, are reference types (§8.2) and are said to have reference semantics.
A variable of a struct type directly contains the data of the struct, whereas a variable of a class type contains a reference to an object that contains the data."
After watching the talk, you know that the last paragraph does not apply to Java's value types, so calling them structs would be very confusing. It would lean on a widely known term but with subtly different semantics.
Also, unlike the C# spec, I would find it weird to call numerical primitives like `float` structs.
meanwhile java still doesnt have string interpolation KAPPA XD
"beautiful objects": it feels strange to me by now to refer to an object as beautiful. in reality working with codebases full of abstractions is a late price you pay for not doing it functionally.
Why not create a new language from all you've learned. Java is becoming very dated.
Because that doesn't help the millions of people and thousands of companies who have invested time and money into their Java knowledge and projects. Creating a new language is easy, porting existing projects to it is mostly a waste of resources. So these people and organisations are better supported by improving Java than by offering them an alternative. (And that's leaving aside that there's basically no alternative that is as battle-tested and comes with as rich an ecosystem like Java does.)
This is the answer: CASH - people who use java would lose jobs, so they have an invested reason to push the dying cart down the road. I remember when java was a buzzword and the government was passing out contracts just based on the fact that if you ran Java, then your opportunity award amount would go up exponentially -- it was a good way to increase your ask from the govt. There were bureaucracies, audits, and other corporate/govt greedy corruption in place to floss more money.
Java is/was a poor choice from the beginning. -- I used to work on the Java source code at red hat and that local college that they were in tandem with. My history with java ensured that I never work with java after 2001. I handled bare-metal problems and I knew java was/is a death trap (for any company seeking independent productivity). Its the perfect corporate greed programming language. I would compile the JVM and find bugs and try to fix major memory problems, they'd stall refactoring. They would literally tell me to hide or mask stuff. Anyway, I stayed far away from it (unless I had to code android or oracle). Its a very bad choice for new projects (and it was bad back in the day, but the cheerleader section out screamed the guys that had their ear to the track and knew better). Today, C#, Python, Rust, C, and C++ is your choice for opportunities. I still keep up with Java because I had such a deep dive in my early student days and career days. I know more about Java than maybe 90% of most java programmers and I won't use it for any corporate or enterprise solutions. Java requires way too much god level wisdom to make it work correctly (and James Gosling did that on purpose (for Sun (for customer retention))). I one time I forked and created my own version of JVM and the java compiler just to fix the problems with Java. I decided to make my own custom language for my own company.
But I am thankful for Java. Java made me aware in my youth that the (corporate^^govt) world does not care about productivity and most of the corporate jobs are just seats beholden by very untalented minds that want a cushy job where the C-Suite guys can't question your knowledge. Its all about CASH and job security in the enterprise^^corporate^^[ corrupted govt ] worlds based on obfuscated information. This presentation was exactly how I expected this "refactor" to go: nothing burger.
@@nipafx If I had asked people what they wanted, they would have said faster horses
Alternatives are already there. Namely, Kotlin, without the porting issue, since it's interopable with Java. I might be wrong, but in my reading Kotlin contains most of what Java 2 could be.
Since a few versions, Java started to add new concepts, e.g. record types, but it's fairly easy to adopt them into Kotlin and extend it instead of making something yet again from zero with not much advantage.
Reified generics are still missing, from Kotlin too, but that's a JVM limitation. And as presented, they upgrade the JVM; so I hope reified generics will arrive at some point, or some unification at least, as in Kotlin (no int vs. Integer anywhere, just Int) and make it fully optimized.
Too little too late.
I don't think. It's not only the Java language, it's the JRE itself, the JVM. Meaning, all JVM-based languages can benefit from these changes, like Kotlin, which is awesome!
Java was the worst plague-language ever released upon humankind.
Java widely introduced the usage of VM (tho it existed before, e.g. SmallTalk), with C-like syntax, simple concepts and complete memory-safety. And mostly sensible names, unlike C++ acronym hell. It undeniably was a big deal and by no accident it took over the software industry.
Just because Java's hair turned white and there are cool kid languages around, does not mean it was a mistake. It made compromizes, yes, and I don't like them now, as many Java devs don't, but it was a great tool for a very long time, and admittedly still a fairly nice language.
I myself praise Kotlin as my favorite pick. Such a productive language, I love it. But Java has due reppect to its name, making garbage collection a common thing, runtime class loading a relatively simple thing, and overall, software development simple. Give it what is due.
Could have done better? I guess, as with everything. But was Java a plague? I don't believe so. Why would you say that?
So basically you will replicate Scala from 15 years ago ._.
Scala added value types to the JVM? Quick, somebody tell the folks working on this for 10 years, so they stop wasting their time!
There is too much historical baggage with Java, and its evolution is too slow to keep up with other technology stacks. It can only be used as a textbook for learning and archaeology.
And yet, Java's virtual threads are an industry leading concurrency programming model (better than callbacks, async/await, and reactive) and not many languages have the same level of pattern matching support that Java has (and will get with future developments in that area). Just to name two recent developments that disprove "too slow".
Like what? An example please of a *technical* baggage which makes Java unusable.
Would be so good if Java gave up on oop. This seems like a step in a good direction. OOP is such a nasty disease.
That's the whole thing of Java. It would be like Rust giving up the borrow checker.
@ Java has many good parts too.
With Rust, borrow checker is an advantage with tradeoffs. Java style OOP then again is much more clearly just a problem with no particular tradeoffs.
@gJonii Yeah, but it's so integral to the philosophy of Java. If you think that this is bad (for probably good reasons), you should use a different language.
In other news: Billion dollar mistake 'null' continues to cost Java devs
I wonder if bytecode could get the "String bang" kind-of syntax, while the language would have a backwards-incompatible change with the questionmark making types nullable; so JARs (bytecode of older versions) still usable as before, only that new source code must add the question mark for explicit nullability. C# did something similar, and C# has a big ecosystem too.
If they add this nullability restriction onto the type definitons themselves... it sounds like a little help, but null should be in the type system, properly. Asking for union types (so T|null) is likely too much, but as in C#, or rather, Kotlin, T? would be so much nicer, to define nullability at each usage.
If indeed nullability will be a flag on the types, I will definitely look at it as a step in the wrong direction. I guess it's backwards-compatible, and hence is chosen. But doesn't feel right.