int x = 16_777_217;
if (x instanceof float f)
// lossless; use `f`
else
// lossy| Project Amber |
| Project Leyden |
| Project Valhalla |
| Project Babylon |
| Project Speedrun |
Slides at slides.nipafx.dev/java-next.
Smaller, productivity-oriented Java language features
Profile:
project / wiki / mailing list
launched March 2017
led by Brian Goetz
Some downsides of Java:
can be cumbersome
tends to require boilerplate
situational lack of expressiveness
Amber continuously improves that situation.
Amber’s main thrust is pattern matching:
records
sealed types
improved switch
patterns
Rounds out the language
by allowing primitives in patterns:
int x = 16_777_217;
if (x instanceof float f)
// lossless; use `f`
else
// lossyDeriving new record instances
from existing ones:
record Point(int x, int y) { }
var p0 = new Point(0, 0);
var p1 = p0 with { x = 1; };(Strawman syntax.)
// ↙ CLASS ↙ state description
class Point(int x, int y) {
// fields
// constructors
// if one matches the state description,
// the class can be "withered"
// accessors
// equals, hashCode, etc.
}(Strawman syntax.)
makes Java more expressive
reduces amount of code
makes us more productive
JDK 21:
records & sealed types
pattern matching basics
text blocks
single-file source launcher
JDK 25:
unnamed variables and patterns
multi-file source launcher
simplified main & module imports
flexible constructor bodies
Current work:
primitive types in patterns (JEP 530)
deconstruction & reconstruction
🎥 Carrier Classes; Beyond Records (Jan 2026)
🎥 Java 21 Pattern Matching Tutorial (Sep 2023)
🎥 Java Language Futures: Fall 2024 Edition (Oct 2024)
Faster startup, shorter time to peak performance, smaller footprint
Profile:
launched May 2022
led by Mark Reinhold and John Rose
Java has really good peak performance,
but also tends to have:
slow startup time
slow warmup time
Early work by the runtime:
class loading
callsite linkage
constant pool resolution
interpretation
profile gathering
JIT compilation (C1, C2)
Can we shift this work?
Java already shifts computation:
compile-time constant folding
class loading
garbage collection
out-of-order execution
…
Let’s shift more computation ahead of time!
Early work depends on:
class/module path content
command line options,
particularly module options
run-time hardware and behavior
Only known during execution.
How to AOT everything?
Leyden introduces AOTCache:
observe JVM
capture decisions in AOTCache
(expansion of CDS Archive)
use as "initial state" during future run
fall back to live observation/optimization
if necessary and possible
# training run (⇝ profile)
$ java -XX:AOTMode=record
-XX:AOTConfiguration=app.aotconf
-cp app.jar com.example.App ...
# assembly phase (profile ⇝ AOTCache)
$ java -XX:AOTMode=create
-XX:AOTConfiguration=app.aotconf
-XX:AOTCache=app.aot
-cp app.jar
# production run (AOTCache ⇝ performance)
$ java -XX:AOTCache=app.aot
-cp app.jar com.example.App ...Shortcut for most cases:
# training run (⇝ AOTCache)
$ java -XX:AOTCacheOutput=app.aot
-cp app.jar com.example.App ...
# production run (AOTCache ⇝ performance)
$ java -XX:AOTCache=app.aot
-cp app.jar com.example.App ...(Open to further improvements.)
Improve startup time by making the classes of an application instantly available, in a loaded and linked state, when the HotSpot JVM starts.
Spring PetClinic benchmarks:
up to ~40% startup time reduction
AOT cache size of ~130 MB
Improve warmup time by making method-execution profiles from a previous run of an application instantly available, when the HotSpot Java Virtual Machine starts.
Benchmark of a 100_000x loop over a simple stream:
~20% run time reduction
AOT cache size increased by ~2.5%
Making it possible to load cached Java objects sequentially into memory from a neutral, GC-agnostic format.
allows use of any garbage collector
does not block when initializing heap
takes longer for warm starts and
requires a CPU core
(Note: The cache contains no application instances.)
Improve startup and warmup time by making optimized native code for an application instantly available when the HotSpot JVM starts.
Benchmarks with javac:
~15% startup time reduction
~75% fewer warmup iterations
for code compilation: AArch64 or x64
training vs production:
same JDK release / architecture / OS
for code compilation: same CPU features & GC
consistent class path
consistent module options
limited use of JVMTI agents
Otherwise, unsuitable portions are ignored.
Leyden’s EA AOTs more:
constant resolution
dynamic proxies
reflection data
unfound classes
Benchmarks show ~70% startup time reduction.
improves Java’s overall footprint
focusses on startup/warmup time
by caching early JVM work
may explore stricter constraints
for more aggressive optimization
expand AOTCache
allow tradeoff between
portability and peak performance
iterative training
better inspectability of training data
📝 Thoughts on Training Runs (Sep 2024)
📝 Selectively Shifting and Constraining Computation
(Oct 2022)
🎥 A Preview of What’s Coming in Project Leyden (Oct 2024)
🎥 Project Leyden: Capturing Lightning in a Bottle (Feb 2024)
🎥 Project Leyden Update #JVMLS (Aug 2024)
Advanced Java VM and Language feature candidates
Profile:
launched July 2014
led by Brian Goetz
Java has a split type system:
primitives
classes
We can only create classes, but:
have identity
have references
All classes come with identity:
extra memory for header
mutability
locking, synchronization, etc.
But not all custom types need that!
All instances come as references:
memory access indirection
nullability
But not all code needs that!
Valhalla’s goal is to unify the type system.
Primary mechanism: value classes.
Potential follow-up work:
null-restriction
specialized generics
universal generics
type classes
java.lang : Integer, Long, Float, Double, Byte, Short, Character, Boolean, Number, Record
java.util : Optional, OptionalInt, OptionalLong, OptionalDouble
java.time : LocalDate, LocalTime, LocalDateTime, ZonedDateTime, OffsetTime, OffsetDateTime, Duration, Instant, Period, Year, YearMonth, MonthDay
java.time.chrono : MinguoDate, HijrahDate, JapaneseDate, ThaiBuddhistDate
value class ComplexNumber {
private double real;
private double imaginary;
// constructor, etc.
}Codes (almost) like a class - exceptions:
class and fields are implicitly final
superclasses are limited
No identity:
"identity" check == compares by state
some operations throw exceptions
(null is the default value)
Benefits:
guaranteed immutability
more expressiveness
more optimizations
When passing objects to or from a method,
the runtime generally references heap objects.
Tracking identity:
required for identity objects
unless escape analysis shows it isn’t
never needed for value objects
⇝ The runtime can load value object fields once
and use the stack to pass them.
Reference flattening:
encode object’s fields in reference
requires extra bit for nullity
limited by atomic writes (⇝ 64 bits)
limited by type information
Flattening would be more applicable with:
performant 128-bit atomic writes
language-level atomicity control
language-level nullity information
generic specialization
Details are in flux, but possibly:
// number can't be null
ComplexNumber! number = // ...Value classes can be type parameters:
List<ComplexNumber> numbers = new ArrayList<>();But if ArrayList<ComplexNumber> is backed by Object[],
it will still be avoided in many cases.
Specialized generics would enable ComplexNumber[],
which allows the JVM to flatten references.
To completely heal the rift, List<int> would be great!
Ideally, int is just the legacy version of Integer!.
⇝ List<int> just works.
Don’t create a value class in order to get performance.
Instead:
"Is the type value-ish?" ⇝ value class
"Is no null needed?" ⇝ restrict nullness
"Do I control concurrency" ⇝ relax atomicity
Performance emerges from domain decisions!
For value classes to feel like primitives,
we need to use them with operators.
Maybe (!) Java will let us define common operations
for suitale types (with type classes):
var one = new ComplexNumber(1, 0);
var i = new ComplexNumber(0, 1);
var x = one + i; // maybe
var y = one * i; // maybe
var z = one $ i; // NO!Value classes, null-restriction, and specialized generics:
fewer trade-offs between
design and performance
no more manual specializations
better performance
can express design more clearly
more robust APIs
Makes Java more expressive and performant.
Value classes are a preview feature in JDK 28.
Everything else is TBD.
📝 State of Valhalla
🎥 Valhalla - Java’s Epic Refactor (Dec 2024)
🎥 Growing the Java Language (Aug 2025)
Extend the reach of Java to foreign programming models such as SQL, differentiable programming, machine learning models, and GPUs
Profile:
launched January 2024
led by Paul Sandoz
Java is adjacent to other programmable systems:
GPUs and FPGAs
SQL databases
differentiable functions
Allow programming them with Java code.
Don’t adapt to each realm in a separate project.
Instead:
make Java code accessible
provide API to read and transform it
let ecosystem provide adaptions
Babylons’s central mechanism is code reflection:
enhancement of "regular" reflection
reaches down into methods/lambdas
symbolic representation of (Java) code
These are called code models.
Abstract syntax tree:
constructed during compilation
closely aligned with Java grammar
too much syntactic info
Bytecode:
created by compiler
specified by JVM Specification
too little important info
The code model design is heavily influenced by the design of data structures used by many modern compilers to represent code. These data structures are commonly referred to as Intermediate Representations (IRs). The design is further influenced by Multi-Level Intermediate Representation (MLIR), a sub-project of the LLVM Compiler Infrastructure project.
Identify code (e.g. with annotation):
@CodeReflection
static double sub(double a, double b) {
return a - b;
}Then:
compiler creates code model
stored in class files
accessible via reflection API
can be transformed by Java code
"Direct" GPU programming:
transform to GPU kernels (OpenCL C or CUDA C)
compile with GPU-specific toolchain
Triton-style:
offer class Triton with static methods
transform to Triton code model
compile with Triton toolchain
@CodeReflection
static void add_kernel2(
Ptr x, Ptr y, Ptr result, int n, int size) {
var pid = Triton.programId(0);
var block_start = pid * size;
var range = Triton.arange(0, size);
var offsets = Triton.add(block_start, range);
var mask = Triton.compare(
offsets, n, Triton.CompareKind.LessThan);
var x = Triton.load(Triton.add(x, offsets), mask);
var y = Triton.load(Triton.add(y, offsets), mask);
var output = Triton.add(x, y);
Triton.store(
Triton.add(result, offsets), output, mask);
}introduces code reflection & code models
allows their transformation
expands Java to foreign programming models
spearheads Java-on-GPU efforts (HAT)
🤷🏾♂️
(Code reflection prototype is being polished for incubation.)
📝 Accelerating Java on Parallel Architectures (Oct 2024)
🎥 Java for AI (Oct 2025)
🎥 Writing GPU-Ready AI Models in Pure Java (Oct 2025)
🎥 ONNX Based Generative AI LLMs in Java (Nov 2025)
Not actually a project
Support easy-to-use, high-throughput, lightweight concurrency and new programming models
Deliverables:
virtual threads
scoped values
structured concurrency
JDK 26:
class initialization doesn’t pin (JDK-8369238)
JDK 27:
structured concurrency in 7th preview (JEP 533)
Current work:
finalize structured concurrency
improve lock info in thread dumps
Interconnecting JVM and native code
Deliverables:
foreign function & memory API
vector API
Foreign APIs:
🎥 FFM API (Aug 2023)
Vector API:
🎥 Fast Java Code with the Vector API (Mar 2023)
📝 FizzBuzz – SIMD Style! (Mar 2021)
Explore techniques to downsize Java object headers in the Hotspot JVM from 128 bits to 64 bits or less
Deliverables:
compact object headers (⇝ 64 bits)
even more compact object headers (⇝ 32 bits)
Provide implementations of
javax.script
for JavaScript based on Chrome V8 and
for Python based on CPython.
No deliverables yet.
2026:
project reestablished
early prototypes are promising