Java 20 has been released on 21st March 2023, and it introduced a range of changes and new functionality. The current version is a non-LTS release, while the following version 21 is set to be a release with Long-Term Support (LTS). We prepared a sneak peek into which JEPs have been accepted into JDK 20, and which ones we are excited to hopefully be accepted next!
But before we jump into the JEPs lined up for Java 20, let’s do a quick overview of the process for updating Java and the concept of enhancement proposals so that you have the full picture on what’s going on.
JDK Enhancement Proposal (JEP) & roadmap process
Development of the Java Development Kit (JDK) is based on the concept of JDK Enhancement Proposals, or JEPs. In essence, these enhancement proposals serve as the roadmap for JDK release projects and all related development activities. The JEP process does not replace the Java community process as that is still the primary way to approve changes in the Java API and language. Rather, Oracle’s intention for introducing the JEPs back in 2010 was to enable OpenJDK contributors to submit ideas to improve the ecosystem. JEPs help track the development status of features intended for delivery in a JDK release project, as well as work that is not linked to a specific release.
At the time of writing, the JEP Index lists 437 enhancement proposals, as well as a number of draft and submitted JEPs. Of all these enhancement proposals, the first 4 are meta-JEPs:
- JEP 0 is the JEP Index of all posted proposals referenced above.
- JEP 1 outlines the process for managing (collecting, reviewing, prioritizing & evaluating, and recording the results) of proposals for JDK enhancement, process, and infrastructure improvements.
- JEP 2 is a template to be used for creating new JEPs.
- JEP 3 describes the JDK release process.
The output of the JEP process is a JDK roadmap that contains proposals for new features as well as other improvement ideas to be considered for inclusion in JDK release projects. The roadmap basically serves as a backlog, covering ideas for at least the next three years, so not all JEPs will make it into the next release.
You can check out the current list of JEPs (drafts and submitted candidates) for the next Java version 21 in JEP 0, as well as the Early-Access Release Notes for changes of this version. OK, now that you understand the process, let’s dive right into what JEPs were accepted into Java 20!
What JEPs have been accepted into JDK 20?
Record patterns
Introduced as first preview in JDK 19 and as second preview in JDK 20. To support data navigation and processing, record patterns ease working with record components. Without changing the syntax or semantics of type patterns, this extends pattern matching for more complex data queries.
The below code example (source https://openjdk.org/jeps/432) shows how the components x
and y
can be elegantly accessed using record patterns, getting rid of the typical calls to p.x()
and p.y()
.
if (o instanceof Point(int x, int y)) {
System.out.println(x+y);
}
Pattern matching for switch statements
Introduced as first preview in JDK 17 and now as its fourth preview in JDK 20. JEP 433 aims to make switch statements more powerful as well as easier to read and maintain. In previous Java versions, the type of a chosen switch selector is restricted to integral primitives, their boxed versions, enums and strings. With this new addition, switches can be used on any type and patterns are used to select a certain case. An example of such a pattern is case Triangle t
. This case will be executed if the selector is of the type Triangle. In addition, the when
clause can be used to further filter which case clause should be executed, i.e. having different cases for different triangles. An example of such a when
clause would be when t.calculateArea() > 100
.
The following code snippet (source https://openjdk.org/jeps/433) summarizes the usage of pattern matching in switch statements:
switch (s) {
case null ->
{ break; }
case Triangle t
when t.calculateArea() > 100 ->
System.out.println("Large triangle");
default ->
System.out.println("A shape, possibly a small triangle");
}
Foreign function & memory (FFM) API
The FFM API has its roots in a wide range of JEPs that have been combined, leading to its first preview in JDK 19 and as its second preview in JDK 20. It allows to invoke foreign functions for Java programs to operate with external code and data, e.g. outside of the Java runtime, without the drawbacks and risks of JNI. The main goal of the FFM API is to have a superior, pure Java development model, and to support a wider range of foreign memory models.
Virtual threads
Introduced as first preview in JDK 19 and as second preview in JDK 20. Virtual threads enhance efficiency when writing, maintaining, and monitoring concurrent applications. They are lightweight, support thread-per-request scalability and may be applied with minimal changes to existing code. A traditional Java thread maps exactly to one OS thread, while virtual threads are not tied to a particular OS thread. As a result, they are cheap to create and you can create as many of them as required.
Vector API
To enhance performance when compared to scalar computations, this API enables vector computations compiled at runtime.
Additions for multithreaded code
In case you are working with multithreaded code, make sure to checkout these additions which provide options to make multithreaded code easier to read or provide performance gains.
Scoped values
With extent-local variables, it is easier to share immutable data within a thread and across child threads in Java. The goal with this update is to simplify reasoning about the data flow for better usability; to improve robustness so that only legitimate callees can retrieve the data shared by a caller; and to improve performance by enabling runtime optimizations and treating shared data as immutable. While this change does not require migrating away from thread-local variables, they are preferably used especially with a large number of virtual threads.
Structured concurrency
With the introduction of an API for structured concurrency, JEP 437 enables the treating of different tasks running in separate threads as a single unit of work. This greatly simplify multithreaded programming and encourage developers to apply concurrent programming by making it easier to ensure the reliability, maintainability, and observability of code.
What JEPs we are excited about after JDK 20
Additions to the type system
The following changes to the type system provide options to write code with a higher performance, or are easier to read and maintain.
Primitive classes
JEP 401 introduces support for a new special kind of value class to define primitive types. The use of primitives enables improved performance due to better memory access and because primitive operations are carried out more efficiently within the CPU. With this update, developers can reap the performance benefits of primitives while retaining abstractions and other benefits of class declarations.
In order to be able to combine the benefits of primitives with typical object orientation, primitive classes need to adhere to the following two rules:
- All fields within a primitive class are defined implicitly final, i.e. they can only be set within a constructor or initializer.
- In addition, primitive classes cannot have fields that implicitly rely on the declaring class.
Primitive classes are declared using the primitive
keyword, i.e.:
primitive class Point implements Shape {
...
}
Value objects
Traditional Java objects offer identity, i.e. their memory location is used to distinguish one object from another. Offering identity is costly at runtime and oftentimes not used in implementations. With this submission, Java’s object model is extended with value classes and value objects. Value classes are identity-free, i.e. they can provide the performance benefits of primitive types while making use of object-oriented concepts. When using the ==
on value objects the values of their fields are used to determine object equality rather than their memory location. Be aware that all fields of value classes are implicitly final and need to be set in an initializer or constructor!
Value classes are declared using the value
keyword, i.e.:
value class Point implements Shape {
...
}
Universal generics
This submission removes the requirement that type parameters need to be reference types by also allowing primitive classes as type parameters. Many existing generic implementations will work out of the box with this new addition, i.e. they can be instantiated with a primitive class as its type argument. But, special care needs to be taken in case the code performs assignments to null, as primitive classes will fail with a null pointer exception.
String Templates
To simplify routine string composition, string templates, aka string literals, contain embedded expressions that are interpreted at runtime. By adding a new kind of expression (string template expression) to Java, JEP 430 makes it simpler to write code with strings that include values computed at runtime. This enables better readability, flexibility in defining the formatting syntax, and improved security with programs that require input values from users.
Further exciting JEPs
- Sequenced collections: adds the SequencedCollection Interface to the standard library, providing the first collection that defines an order over the elements within the collection.
- Asynchronous stack trace API: Introduces a new API for collecting stack traces asynchronously.
- Classfile API: Adds a new API to replace ASM (or cglib, or another bytecode library) that will provide a way to read, write, and transform Java class files.
Summary: why we’re excited for Java 20
Overall, the updates in Java 20 promise more flexibility in building high-performing software. If you’re excited to try it, check out the open-source builds! But more importantly, make sure you don’t miss our updates on Java and other software development topics by signing up to our newsletter.
Using Java to develop awesome software? Save time by auto-generating your unit tests with Symflower. It’s available for IntelliJ IDEA, VS Code, and CLI – give it a whirl and let us know what you think!