Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Will Valhalla Fix Tony’s Billion $ Mistake?

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →
Avatar for José José
October 05, 2026

Will Valhalla Fix Tony’s Billion $ Mistake?

In March 2027, in JDK 28 (JVM gods willing!), after more than 12 years of effort, the Valhalla project will deliver its first feature: Value Classes (JEP 401) as a preview feature. Value classes are defined as regular classes with a "value" keyword in front. They are backward compatible with your code written before Java 28, without you having to recompile it.
Value classes bring new optimization opportunities at the JVM level: scalarization on stack and flattening on heap. For that, the Java specification had to be reinterpreted and enhanced, challenging us to reconsider some of the fundamentals on which Java was created 30 years ago. What does == mean? Is a reference always a pointer? Can an instance of a value class be null? Can you observe the transition between the default values and the final values of fields during object construction? And more.
This presentation covers all these questions, showing the trade-offs that need to be made in order to bring value classes to the Java platform.
You will hear about new code patterns, performance, and type safety. And, as value classes are just the first step, we will cover what Valhalla should bring in the future.

Avatar for José

José

October 05, 2026

More Decks by José

Other Decks in Programming

Transcript

  1. Will Valhalla Fix Tony’s Billion $ Mistake? Exploring New Ways

    to Manage Your In Memory Data José Paumard Java Developer Advocate Java Platform Group Rémi Forax Associate Professor Université Gustave Eiffel
  2. https://twitter.com/Nope! https://github.com/forax https://speakerdeck.com/forax OpenJDK, ASM, Tatoo, Pro, etc… One of

    the fathers of invokedynamic (Java 7) Lambda (Java 8), Module (Java 9) Constant dynamic (Java 11) Record, Pattern Matching (Java 17 / 21) Valhalla (Java 28+)
  3. Tony Hoare’s 1B$ mistake Null reference violations have cost in

    terms of programmer time, user discomfort and general damage in the order of a billion $. Tony Hoare, QCon London, 2009 4 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  4. Tune in! Inside Java Newscast Inside.java JEP Café 6 Inside

    Java Podcast Road To 25 series Java 27 Launch Cracking the Java coding interview Copyright © 2026, Oracle and/or its affiliates 10/4/2026 Sip of Java
  5. OpenJDK is the place where it all happens https://openjdk.org/ 7

    Copyright © 2026, Oracle and/or its affiliates | https://openjdk.org/projects/Valhalla/ 10/4/2026
  6. OpenJDK is the place where it all happens https://jdk.java.net/ 8

    Copyright © 2026, Oracle and/or its affiliates 10/4/2026
  7. OpenJDK is the place where it all happens https://jdk.java.net/28/ 9

    Copyright © 2026, Oracle and/or its affiliates 10/4/2026
  8. OpenJDK is the place where it all happens Prefer the

    JDK 28 EA version https://jdk.java.net/ 10 Copyright © 2026, Oracle and/or its affiliates 10/4/2026
  9. OpenJDK is the place where it all happens https://openjdk.org/jeps/401 11

    Copyright © 2026, Oracle and/or its affiliates 10/4/2026
  10. OpenJDK is the place where it all happens https://openjdk.org/jeps/539 12

    Copyright © 2026, Oracle and/or its affiliates 10/4/2026
  11. The Valhalla Project OpenJDK project lead by Brian Goetz https://openjdk.org/projects/valhalla/

    Started on July, 2014! Brian Goetz 13 Copyright © 2026, Oracle and/or its affiliates | Dan Smith 10/4/2026 John Rose
  12. Primitive vs. Object in Java Strong separation between primitives and

    Objects Java code uses primitives directly (CPU and GPU friendly) and uses Objects through references Primitives are not part of the Object Oriented Programming world (no encapsulation, no abstraction) 14 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  13. Valhalla / JEP 401 Bring the benefits of primitives to

    objects and classes Enable flatter and denser memory layouts Enable adding new primitive-like classes Compatible migration of existing value-based classes Healing the reference-primitive divide Enable runtime specialization of generics 15 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  14. JEP 401 Pull Request Friday 9th 9:30 – 10:20 Room

    6 17 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  15. Valhalla 1) What does it mean to lack identity? What

    is object identity? How does it relate to mutability? 2) How can you improve performance? 3) How can you save memory with value objects? 19 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  16. What is Object Identity and How Does it Relate to

    Mutability? 20 Copyright © 2026, Oracle and/or its affiliates 10/4/2026
  17. What is Object Identity? The identity of an object is

    its address in memory record Song( String title, short duration) {} OxFF238E64 OxFF239A24 Song String title hashCode beatIt 1430316469 var beatIt = new Song("Beat it", 256); value duration 256 OxFF14C874 B 21 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026 e a t i t
  18. What is Object Identity? There can only be one copy

    of any object in memory OxFF148F32 playList class PlayList { String title; ArrayList<Song> songs; // constructors and methods } var playList = new PlayList("80s"); playList.add(beatIt); playList.add(thriller); playList.add(billieJean); PlayList String title hashCode 55419 songs value OxFF238E64 Copyright © 2026, Oracle and/or its affiliates | OxFF18A060 ArrayList size 3 elementData 22 OxFF564FA4 10/4/2026 8 OxFF024594 0 s
  19. What is Object Identity? There can only be one copy

    of any object in memory OxFF148F32 playList class PlayList { String title; ArrayList<Song> songs; // constructors and methods } var playList = new PlayList("80s"); playList.add(beatIt); playList.add(thriller); playList.add(billieJean); PlayList String title hashCode 55419 songs value OxFF238E64 Copyright © 2026, Oracle and/or its affiliates | OxFF18A060 ArrayList size 3 This allows for mutable objects elementData 23 OxFF564FA4 10/4/2026 8 OxFF024594 0 s
  20. Memory Layout of an Identity Object record Song(String title, short

    duration) {} Header 64 bits title 32 (64) bits duration padding 16 bits 16 (48) bits The header carries the following information: - Class pointer - GC info - Locking - Object’s stable identity hash code - Bits for Valhalla JEP 450: https://openjdk.org/jeps/450 24 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  21. What is an Object without Identity? The identity of an

    object is its address in memory No identity means no address, thus no mutability All the fields and class itself are final An object without identity behaves like a primitive value 3 is the size of the list it is 3, wherever it lives in memory 25 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  22. Value Objects vs. Identity Objects 1) A value class is

    a class whose instances do not have identity 2) These instances are called value objects 3) A non-value class is called an identity class You want the best of both worlds! - Abstraction offered by classes - Performance offered by primitives 26 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  23. Value Objects value class Song { String title; short duration;

    // constructors, methods } value record Song(String title, short duration) {} var beatIt = new Song("Beat it", 256); 27 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  24. Value Objects Since value objects give up their identity, the

    JVM can use the value objects directly (no pointer) Two consequences: 1) No object header for value objects 2) You need to reinterpret address-based operations 28 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  25. Demo 1) Création d’un value record 2) Différence de sémantique

    avec == sur une value class 3) Hashcode sur une value class 4) Synchronization 5) Weak reference 30 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  26. Object Mutation in Constructors Problem: you can observe field mutation

    during object construction class Song { String title; Song(String title) { IO.println("Title: " + this); this.title = title; } public String toString() { return this.title; } } > var song = new Song("Beat it"); Title: null 31 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  27. Demo Strict initialization 1) Classe normale avec appel à super

    en premier, qui montre la mutation d’un champ final 2) Ne compile plus si l’on met value 3) Montrer comment mettre le super à la fin règle les problèmes, le print après l’appel à super() 33 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  28. Object Mutation in Constructors Value objects have strict fields, their

    mutation cannot be observed value class Song { String title; Song(String title) { IO.println("Title: " + this); this.title = title; } public String toString() { return this.title; } } Cannot reference 'this' before superclass constructor is called 34 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  29. Object Mutation in Constructors Reason: in value classes, the call

    to super() is added at the end of the constructor by the compiler value class Song { String title; Song(String title) { IO.println("Title: " + this); this.title = title; super(); } } 35 Copyright © 2026, Oracle and/or its affiliates | public String toString() { return this.title; } Cannot reference 'this' before superclass constructor is called 10/4/2026
  30. Object Mutation in Constructors Reason: in value classes, strict fields

    must be initialized before the call to super() value class Song { String title; Song(String title) { super(); this.title = title; } public String toString() { return this.title; } } strict field title is not initialized before the supertype constructor has been called 36 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  31. Object Mutation in Constructors 1) Strict fields must be initialized

    before the call to super() 2) You can use this after the call to super() value class Song { String title; Song(String title) { this.title = title; super(); IO.println("Title: " + this); } public String toString() { return this.title; } } > var song = new Song("Beat it"); Title: Beat it 37 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  32. Value Class Strict Initialization Rules A value class has strict-init

    fields They must be initialized before the call to super() If super() is not called explicitly, the compiler adds it at the end of the constructor 38 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  33. Demo 1) Mot-clé value sur une classe abstraite 42 Copyright

    © 2026, Oracle and/or its affiliates | 10/4/2026
  34. Abstract Class? A value class can only extend an abstract

    value class or Object abstract class AbstractTitle { value class Song extends AbstractTitle { String title; AbstractTitle(String title) { this.title = title; super(); } Song(String title) { super(title); } } Value classes may only extend abstract value classes or 'java.lang.Object' public String title() { return title; } } 43 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  35. Abstract Class? A value class can only extend an abstract

    value class or Object value abstract class AbstractTitle { value class Song extends AbstractTitle { String title; AbstractTitle(String title) { this.title = title; super(); } Song(String title) { super(title); } } public String title() { return title; } } 44 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  36. Abstract Class? On the other hand, any class can extend

    abstract value class value abstract class AbstractTitle { class Song extends AbstractTitle { String title; AbstractTitle(String title) { this.title = title; super(); } Song(String title) { super(title); } } public String title() { return title; } } 45 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  37. Abstract Value Classes Two rules for abstract classes: 1) An

    identity class can extend an abstract value class 2) A value class can only extend an abstract value class (or Object) The value keyword for abstract classes means valueenabled, this class respects the strict initialization rules 46 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  38. Benchmarks: Let’s Make a Mixtape! Let us run some code

    and see the performance improvements And create Mixtapes from songs and playlists © Let’s Make a Mixtape https://www.letsmixtape.com/ 48 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  39. Benchmarks value record ValueSong(String title, short duration) {} value record

    ValuePlayList(String title, ValueSong[] songs) { ValuePlayList { Objects.requireNonNull(title); songs = songs.clone(); // defensive copy } public ValueSong[] songs() { return songs.clone(); // defensive copy } } 49 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  40. Benchmarks value record ValueSong(String title, short duration) {} value record

    ValuePlayList(String title, ValueSong[] songs) {} record IdentitySong(String title, short duration) {} record IdentityPlayList(String title, IdentitySong[] songs) {} 50 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  41. Benchmarks – Creating a MixTape V1 Adding the durations of

    the songs to create a mixtape V1: summing durations as shorts Song mixTapePrimitive(PlayList playList) { var duration = (short) 0; Songs are read from an array No object creation Sum of shorts in a loop for (var i = 0; i < playList.songs.length; i++) { duration += playList.songs.get(i).duration(); } return new Song(playList.title, duration); } 51 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  42. Benchmarks – Creating a MixTape V2 Adding the durations of

    the songs to create a mixtape V2: adding songs Song mixTapeObject(PlayList playList) { var song = new Song(playList.title, (short) 0); for (var i = 0; i < playList.songs.length; i++) { song = new Song(song.title(), (short) (song.duration() + playList.songs[i].duration())); } Songs are read from an array A new Song is created in each iteration Durations are added one by one return song; } 52 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  43. Benchmarks – Creating a MixTape V3 Adding the durations of

    the songs to create a mixtape V3: reducing a stream of songs Song mixTapeReduce(PlayList playList) { Songs are read from an array The calculation is a stream reduction return Arrays.stream(playList.songs).reduce( new Song(playList.title, (short) 0), (s1, s2) -> new Song(s1.title(), (short) (s1.duration() + s2.duration()))); } 53 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  44. Benchmarks – Results Results for Identity Classes Perf. MixTape 100

    songs MixTape 100 songs MixTape 100 songs [V1 – Primitive] [V2 – Object] [V3 – Stream] Score Error 33 ± 0.2 190 ± 2.6 191 ± 0.8 Units ns/op ns/op ns/op Results for Value Classes, no array flattening Perf. MixTape 100 songs MixTape 100 songs MixTape 100 songs 54 Copyright © 2026, Oracle and/or its affiliates | [V1 – Primitive] [V2 – Object] [V3 – Stream] Score Error 33 ± 0.69 33 ± 0.53 196 ± 1.76 10/4/2026 Units ns/op ns/op ns/op
  45. Benchmarks – GC Count and Time Results for Identity Classes

    Perf. Creating a MixTape [V1 – Primitive] Creating a MixTape [V2 – Object] Creating a MixTape [V3 – Stream] Score Units 70 count 138 count 122 count Score Units 43 ms 110 ms 93 ms Score Units 0 count 0 count 19 count Score 0 0 16 Results for Value Classes Perf. Creating a MixTape [V1 – Primitive] Creating a MixTape [V2 – Object] Creating a MixTape [V3 – Stream] 55 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026 Units ms ms ms
  46. Scalarization on Stack So your source code: Song createMixTape(PlayList playList)

    { var song = new Song(playList.title, (short) 0); for (var i = 0; i < playList.songs.length; i++) { song = new Song(song.title, (short) (song.duration() + playList.songs[i].duration())); } return song; } 56 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  47. Scalarization on Stack Is executed in that way at the

    assembly level (JIT) (String, short) createMixTape(PlayList playList) { var song = (playList.title, (short) 0); for (var i = 0; i < playList.songs.length; i++) { song = (song.title, song.duration + playList.songs[i].duration); } return (song.title, song.duration); } (this pseudo code, not Java) 57 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  48. Scalarization on Stack How is the code optimized? Objects are

    scattered as values Only the values of their fields are passed, as 1) The parameters and the returned object are stored in registers 2) Local variables and fields are stored in registers 58 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  49. Why Does Not It Work with Streams? Short answer: because

    of type erasure The VM sees a stream of objects, not a Stream<Song>, so the value type nature of Song is not seen and cannot be used We need specialized generics for that, and we are not there yet 59 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  50. What is Flattening? length Song[] songs Header If Song is

    an identity class An array of Song is an array of pointers Song String title hashCode 1430316469 duration 256 62 Copyright © 2026, Oracle and/or its affiliates | value 10/4/2026 B e a t i t
  51. What is Flattening? 1 title duration 249 1 title duration

    278 String hashCode 1430316469 B e a value 63 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026 t i t padding duration 256 padding title padding length Song[] songs Header For Value Objects, flattening consists in encoding the values instead of pointing to the memory location 1
  52. What is Flattening? 1 title duration 256 1 title duration

    256 padding duration 256 padding title padding length Song[] songs Header For Value Objects, flattening consists in encoding the values instead of pointing to the memory location 1 An extra 8 bits information tells if the flattened reference is null or not: null_marker It is still a big memory saving! 64 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  53. Constraints on Flattening There is a limitation on the size

    of the objects you can flatten Null references → you need a 8 bits marker Atomically → maximum size of 64 bits That leaves 56 bits for your value object 65 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  54. Constraints on Flattening value record ValueSong(String title, int duration) {}

    // No flattening for you! The Song value object is 32 bits + 32 bits So it cannot be flattened 66 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  55. Constraints on Flattening value record ValueSong(String title, int duration) {}

    // No flattening for you! The Song value object is 32 bits + 32 bits So it cannot be flattened 67 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  56. Benchmarks – Results Results for Value Classes, no array flattening

    Perf. MixTape 100 songs MixTape 100 songs MixTape 100 songs [V1 – Primitive] [V2 – Object] [V3 – Stream] Score Error 33 ± 0.69 33 ± 0.53 196 ± 1.76 Units ns/op ns/op ns/op Results for Value Classes, with array flattening Perf. MixTape 100 songs MixTape 100 songs MixTape 100 songs 68 Copyright © 2026, Oracle and/or its affiliates | [V1 – Primitive] [V2 – Object] [V3 – Stream] Score Error 49 ± 0.2 53 ± 0.2 2611 ± 25.5 10/4/2026 Units ns/op ns/op ns/op
  57. Value Object Decoding songs[1] title duration 256 0 padding A

    value object from an array needs to be decoded using shift and mask var song = song[i] var null_marker = song & 0xFF var title = song >>> 32 var duration = (song >>> 16) & 0xFFFF Usually, those operations are fast and the RAM access is slow Microbenchmark magnified them because the array is in the caches 69 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  58. Benchmarks – Results Results for non-flattened vs. flattened Value classes

    100 songs 1_000 songs 10_000 songs 100_000 songs 1_000_000 songs Score Error 33 ± 0.3 421 ± 1.8 4.32 ± 0.11 79.9 ± 4.2 2.71 ± 0.14 Value classes flattened 100 songs 1_000 songs 10_000 songs 100_000 songs 1_000_000 songs 70 Copyright © 2026, Oracle and/or its affiliates | Score Error 54 ± 0.5 502 ± 3.3 5.24 ± 0.05 51.3 ± 0.33 507 ± 7.0 10/4/2026 Units ns/op ns/op s/op s/op ms/op Units ns/op ns/op s/op s/op s/op
  59. Benefits of Flattening 1) Denser storage 2) No extra pointer

    dereferencing 3) Localized storage so no pointer chasing The last two points are hard to see because Java GCs are moving collectors, so they already group objects together 71 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  60. How Does it Work Under the Hood? 72 Copyright ©

    2026, Oracle and/or its affiliates 10/4/2026
  61. Observing a "Real Application" Let us use JFR to see

    what is happening during the benchmark Identity objects: almost 2GB of Song objects are created 73 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  62. Observing a "Real Application" Let us use JFR to see

    what is happening during the benchmark Value objects: less than 3MB of Song objects are created 74 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  63. Observing a "Real Application" Here are the total allocations for

    Song[] and Song 75 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  64. Value Class is a HotSpot Optimization Value classes are managed

    using pointers in the interpreter The JIT (C1, C2) remove allocation and indirection when the bytecode is tranformed to machine code Same bytecode when using an identity class or a value class 76 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  65. Java Compiler and VM (JEP 539) When compiling a value

    class - The compiler clears the ACC_IDENTITY modifier bit of the class file - The compiler sets ACC_STRICT_INIT on all fields 77 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  66. JVM Strategy for Loading Classes In Java classes are loaded

    lazily A class is not loaded when referenced as a field type To trigger field flattening optimizations, the JVM needs to know if a given field type is a value class So it needs to load the value classes earlier 78 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  67. Java Compiler and VM (JEP 539) When compiling a class

    that uses value classes the compiler inserts an attribute LoadableDescriptors that lists the classes that should be pre-loaded The VM loads these classes early to check if they are value classes 79 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  68. JDK Classes Retrofitted as Value Classes Most existing classes annotated

    with @ValueBased are now value classes - Optional and most classes of java.time - all wrappers Boolean, Integer, etc… 80 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  69. JDK Classes Retrofitted as Value Classes This may break some

    existing code as @ValueBased contract was not enforced before var key = new Integer(32); synchronized(key) { // breaks with JDK 28 --enable-preview } But who would be foolish enough to do that? 81 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  70. Preparing Your Code for JEP 401 You can already -

    use flexible constructor (JEP 513) to write super() call at the end of the constructor - do not use == on objects, even when overriding equals() - do not synchronize on something you do not own - do not create a WeakReference on something you do not own 82 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  71. Value Classes Wrap up Mantra: code like a class, works

    like an int - Scalarization is done by the JIT - Flattening if payload size is less than 56 bits - No need to recompile your application (almost true!) - Retrofit Optional, LocalDate, Integer, Double 83 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  72. Challenges 1) How to improve heap flattening? 2) How to

    create user-defined primitive types? 85 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  73. Field Flattening Currently HotSpot supports four kinds of field and

    array flat layout atomic non_atomic 86 Copyright © 2026, Oracle and/or its affiliates | null_marker null_free Limited to 56 bits Limited to 64 bits Must be strict final No restriction 10/4/2026
  74. How to Improve Heap Flattening? How to add information about

    - nullability? - atomicity? Non-atomic read only fields and array elements support nullable Non-atomic read/write fields and array elements are also null-restricted 87 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  75. Exploration 1: Null-Restricted Types Let's help flattening by adding nullability

    markers - ! or ? sigils at the end of a type - ! for strictness/certainty - ? for uncertainty: Boolean!, Optional!, Complex?, etc 88 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  76. Bang ! As a Contract Extends Java to add !

    at the end of a type of a field value record Song(String title, short duration) {} Song! means that this field cannot be null value record GrammyAward(Song! song, short year) {} 89 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  77. Bang ! As a Contract A null-restricted field cannot be

    set to null value record Song(String title, short duration) {} value class GrammyAward { private Song! song; private short year; GrammyAward(Song song, short year) { this.song = song; // the VM can throw a NullPointerException here this.year = year; super(); } } 90 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  78. Using ? Instead of ! Like in Kotlin: String s

    = null; // Not valid in Kotlin, valid in Java Adding ? requires to change the semantics of Java This is not a backward compatible change 91 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  79. Using ! on Parameters with Identity Objects value record Song(String!

    title, int duration) {} // fits in 64 bits! value record GrammyAward(Song! song, short year) {} static boolean isGrammy(List<GrammyAward> grammyAwards, Song! song) { return grammyAwards.stream() .anyMatch(grammyAward -> grammyAward.song().equals(song)); } This is equivalent to Objects.requireNonNull() on the parameter 92 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  80. Creating an Array with ! The array cannot be initialized

    to null var songs = new Song![4]; // does not compile You need a special syntax var songs = new Song![4] {index -> new Song(DEFAULT_TITLE, DEFAULT_DURATION); 93 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  81. Method Selection and ! Because of backward compatibility, ! cannot

    be used in method selection class Player { void play(Object o) {} } class MusicPlayer extends Player { void play(Song! c) {} } MusicPlayer player = new MusicPlayer(); player.play(null); Which method is called: Player.play() or MusicPlayer.play()? 94 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  82. Is Declaring ! at Type Level a Good Idea? null-restricted

    or non-atomic look more like storage keywords than markers on types Also those keywords are implementation decisions, not something the user should control The result of the exploration is: ! will not be introduced for value classes 95 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  83. Exploration 2: Primitive Classes A primitive class is a value

    class that acts like a primitive /* primitive */ record Complex(double re, double im) {} class Holder { Complex complex; // null-restricted Holder() { // this.complex is initialized with Complex(0d, 0d) } } 96 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  84. Primitive Classes A primitive class is a value class that

    acts like a primitive - Non-atomic on heap, like primitives (full flattening) - Non-null on heap, like primitives - Have a default value on heap, like primitives 97 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  85. Giving Up Encapsulation A primitive class → no identity, no

    encapsulation Fields are all independent → no way to enforce invariants on fields A primitive class is a compound of all its fields 98 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  86. Default Value The default value is only used for fields,

    like primitives class Holder { Complex complexField; // set to the default value void someMethod() { Complex localComplex; // not set to the default value IO.println(complexField); // prints Complex(0, 0) IO.println(localComplex); // does not compile! } } 99 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026 Variable 'localComplex' might not have been initialized
  87. Arrays Arrays are stored in a flattened representation var complexes

    = new Complex[10]; // each element is initialized with Complex.default The array is fully flattened 100 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  88. Backward Compatibility Issues Primitive class instances on stack can be

    null var complexMap = new HashMap<String, Complex>(); Complex complex = complexMap.get("origin"); // complex is null 101 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  89. Null Primitive Instances are Allowed on Stack Primitive class instances

    on stack can be null value class Holder { Complex c; // null restricted Holder(Complex c) { Objects.requireNonNull(c, "c is null"); // good practice this.c = c; } Complex f(Complex c) { // c is nullable here return c == null ? Complex.default : c; } } 102 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  90. From the VM Point of View We need a handshake

    between the field and the class - the field has to be marked as null_restricted - the VM has to check that the type is a primitive class The latter can be done using a stricter LoadableDescriptors (fails if not a primitive class) So no backward compatible change from an existing class to a primitive class and vice-versa 103 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  91. From Identity to Primitive Identity Class Give up Identity Value

    Class Get scalarization and 56 bits flattening Give up Encapsulation Primitive Class 104 Copyright © 2026, Oracle and/or its affiliates | Get full flattening, default values and operator overloading 10/4/2026
  92. So, Will Valhalla Fix Tony’s 1B$ mistake? Short answer: no

    106 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  93. Roadmap to Valhalla in JDK 28 JEP 513: Flexible Constructor

    Bodies (Final in 25) JEP 401: Value Objects (Preview) JEP 539: Strict Field Initialization in the JVM (Preview) 107 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  94. Roadmap to Valhalla for Later JEP Draft: Primitive Class +

    non-null fields? JEP 402: Enhanced Primitive Boxing (int ≈ Integer!) Type Classes (operator overloading for primitive class) Parametric JVM (List) 108 Copyright © 2026, Oracle and/or its affiliates | 10/4/2026
  95. Valhalla Features Value Objects Null restricted syntax Primitive class Parametric

    JVM 109 Copyright © 2026, Oracle and/or its affiliates | Preview in 28 Failed experiment Future proposal Future direction 10/4/2026