Core Java

Java 15 New Features Tutorial

In this article, we provide a tutorial about the new features of Java 15. With a lot of improvements and modernization features, Java 15 arrived at the beginning of September. Let’s see them all together!

1. Introduction

Java 15 came with fourteen new features, grouped in the following categories:

Java 15
  • New Features
    • Edwards-Curve Digital Signature Algorithm (EdDSA)
    • Hidden Classes
  • Incubating and Preview Features
    • Sealed Classes – first preview
    • Pattern Matching for instanceof – second preview
    • Records – second preview
    • Foreign-Memory Access API – second incubator
  • Preview and Experimental Features
    • ZGC: A Scalable Low-Latency GC
    • Text Blocks
    • Shenandoah
  • Modernizing the JDK
    • Deprecated
      • Biased locking
      • RMI Activation
    • Removed
      • Nashorn JavaScript Engine
      • Solaris and SPARC Ports
    • Reimplemented
      • Legacy Datagram Socket API

2. Pre-requisites

For the next items with code examples, download one of this Java 15 version in your machine:

  • Oracle Open JDK – offered under the open-source GNU General Public License v2, with the Classpath Exception (GPLv2+CPE).
  • Oracle JDK 15 – offered under a commercial license for those who want commercial support.

In this article, we’ll use Oracle Open JDK and the examples will be executed on IntelliJ 2020.2 with Java 15 support. Download here as you wish. Make sure you got your proper OS version.

3. Java 15 New Features

3.1 Edwards-Curve Digital Signature Algorithm (EdDSA)

I’ll admit that feature it’s beyond my knowledge of encryption. Until today, I just used Java standard encryption. However, I’ll talk briefly about this feature.

Basically, the EdDSA (JEP 339) implements Edwards-Curve Digital Signature Algorithm (EdDSA) as described by RFC 8032. According to JDK documentation, EdDSA is a modern elliptic curve signature scheme that has several advantages over the existing signature schemes in the JDK.

The goal is to develop a platform-independent implementation of EdDSA, in addition, build a better performance than the existing ECDSA implementation (which uses native C code) at the same security strength.

Find here more details about this feature.

3.2 Hidden Classes

Hidden classes (JEP 371) is a feature more interesting to framework developers (Spring guys, I’m talking about you!). Frameworks are the target for this feature that generate classes at run time and use them indirectly, via reflection.

Standard APIs that define a class ClassLoader::defineClass and Lookup::defineClass are indifferent to whether the bytecodes of the class were generated dynamically (at run time) or statically (at compile time).

Using Lookup::defineHiddenClass we can create a hidden class. This causes the JVM to derive a hidden class from the supplied bytes, link the hidden class, and return a lookup object that provides reflective access to the hidden class.

Since this article is focused on JDK, I won’t put any example about this feature, but I’m intending to do it in a near future.

4. Incubating and Preview Features

Incubator modules are non-final APIs and non-final tools disposable for developers, allowing them to give feedback to improve the quality of these features.

4.1 Sealed classes

A Sealed class or interface (JEP 360) can be extended or implemented only by those classes and interfaces permitted to do so.

The idea here is to allow the author of class or interface to control which code is responsible for implementing it, providing a more declarative way instead of use access modifiers (private, public, protected, default).

A class is sealed by applying the sealed modifier to its declaration.

package com.example.jcg.sealed;

public abstract sealed class Animal permits Bird, Cat, Dog{
    public abstract void makeNoise();

With the modifier permits, we define the classes that can implement the superclass. In addition, a class that extends a sealed class may be final to prevent the class hierarchy from being extended.

When a class is not in super class, we got a compilation error when try to extend it:

package com.example.jcg.sealed;

public class Human extends Animal{

    public void makeNoise() {
        System.out.println("Human cry.");
java: class is not allowed to extend sealed class: com.example.jcg.sealed.Animal

4.2 Pattern Matching for instanceof

Java 14 brings this feature on JEP 305. On this second preview implemented in JEP 375, the pattern matching allows developer a more concise and safe extraction of object’s components.

We are familiar with instanceof idiom, using it with some code lines: with instanceof

Character obj = new Character("Bilbo Baggins");
        if (obj instanceof Character) {
            Character c = obj;
        } else {
            System.out.println("Not character.");

Using the pattern matching instanceof in Java 15, we got a cleaner way to do this check making the instanceof to cast into a variable the matched object. with instanceof in Java 15

Character obj = new Character("Bilbo Baggins");
        if (obj instanceof Character c) {
        } else {
            System.out.println("Not character.");

4.3 Records

Records are a new kind of class in Java. Proposed on JEP 359, was delivered as a preview feature in JDK 14. This re-preview in JDK 15 (JEP 384) is for refinements based on feedback and to support additional forms of local classes and interfaces in the Java language.

4.3.1 Less verbose more productivity

A complaining that I always listened about Java is: “Java is too verbose.”. Ok, I agree with that. Some Java classes mean nothing in our journey into coding, they’re just data carriers that involve a lot of low-value, constructors, accessors, equals, hashCode and there it goes.

To enhance the Java language, Records introduces a new kind of type declaration. The purpose of a record is to use a small group of variables considering them as a new kind of entity.

package com.example.jcg.records;

record BMICalculator(double height, double weight) {

    public double calculate () {
        return weight / (height * height);

The keyword record will define our class as a Record type. As noticed, the BMICalculator class discards the use of local accessors (getters and setters) and we can focus on our implementation in the method calculate().

Furthermore, the local variables (in this case height and weight) will automatically have a public accessor with the same name and return type as that variable.

So, Records makes code cleaner and faster for a better approach to understand how the class works, making the development easier.

4.4 Foreign-Memory Access API

The first incubator of Foreign-Memory Access API was introduced on JEP 370 in JDK 14. The purpose of this second incubator in JDK 15 (JEP 383). This incubating targets the refinement and enhancement of that feature.

This API allow Java programs to safely and efficiently access foreign memory outside the Java heap. By providing a targeted solution to the problem of accessing foreign memory, developers will be freed of the limitations and dangers of existing APIs.

The foreign-memory access API introduces three main abstractions: MemorySegment, MemoryAddress and MemoryLayout.

5. Preview and Experimental Features

The following preview features were promoted to product features after enhancements and feedback from the Java community. Here we’ll see what features are them.

5.1 ZGC: A Scalable Low-Latency GC

The Z Garbage Collector, also known as ZGC, is a scalable low-latency garbage collector. Integrated into JDK 11 (JEP 333) the goal is to reduce the pause times of GC, improving Java application performance. With JEP 377, ZGC change from an experimental feature into a production feature.

ZGC is enabled today with -XX:+UnlockExperimentalVMOptions -XX:+UseZGC command-line options, however with product promotion, these the -XX:+UnlockExperimentalVMOptions is no longer needed.

These are some highlighted points after feedback and enhancements made during ZGC experimental period:

  • Concurrent class unloading
  • Uncommitting unused memory (JEP 351)
  • Maximum heap size increased from 4TB to 16TB
  • Minimum heap size decreased to 8MB
  • -XX:SoftMaxHeapSize
  • Support for the JFR leak profiler
  • Support for class-data sharing
  • Limited and discontiguous address spaces
  • Support for placing the heap on NVRAM
  • Improved NUMA awareness
  • Multi-threaded heap pre-touching

5.2 Text Blocks

A text block is a multi-line string literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over format when desired. This feature was introduced in JEP 355 and now is available as a permanent feature in Java language (JEP 378).

When we needed to write a multi-line string like an SQL script, we need to do as below:

Traditional String multi-line

String sql = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n" +
            "WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
            "ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";

Now, with text blocks we can do this in a cleaner and easier way:

Text block String multi-line

String sql = """
             WHERE "CITY" = 'INDIANAPOLIS'
             ORDER BY "EMP_ID", "LAST_NAME";

No more need to use \n to break lines or \ and + to concatenate when build a string in multiple lines. This is a prettier and practical way to do that.

5.3 Shenandoah

Shenandoah is an algorithm that reduces GC pause times by doing evacuation work concurrently with the running Java threads. Integrated in JDK 12 (JEP 189) , now this feature is promoted to the product in JDK 15 (JEP 389).

The intent of Shenandoah feature is not replace the default GC, which remains G1, but offers in Open JDK a low-pause time collector. Another propose in this JEP is not to change the Shenandoah development process, which will continue to support both the latest JDK and popular LTS/STS JDKs.

To use this feature, in JDK 12 until JDK 14, we need the JVM: XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC. Now in JDK 15, the option -XX:+UseShenandoahGC is no longer needed.

Details about Shenandoah algorithm can be found here.

6. Modernizing the JDK

To preserve the reliability and maintainability in JDK as long as the language evolves, some features are outdated or has their use reduced and replace by new and enhanced features. Moreover, a feature is never removed before being deprecated for at least one release first. JDK 15 deprecates two features and removes two other, that were previously deprecated.

6.1 Deprecated Features

6.1.1 Biased locking

Biased locking is an optimization technique used in the HotSpot Virtual Machine to reduce the overhead of uncontended locking. The JEP 374 disables biased locking by default, and deprecate all related command-line options.

6.1.2 RMI Activation

RMI Activation is an obsolete part of RMI that has been optional since JDK 8. This RMI mechanism allows RMI-based services to export stubs whose validity exceeds the lifetime of a remote object or a JVM that contains it. In JDK 15 (JEP 385) this mechanism is deprecated for future removal.

6.2 Removed Features

6.2.1 Nashorn JavaScript Engine

The Nashorn JavaScript engine was first incorporated into JDK 8 via JEP 174 as a replacement for the Rhino scripting engine. When it was released, it was a complete implementation of the ECMAScript-262 5.1 standard.

With ECMAScript rapid pace evolution, Nashorn was difficult to maintain. This feature was deprecated in JDK 11 (JEP 355) and now is been removed in JEP 372.

The below packages will be permanently removed:

  • jdk.scripting.nashorn – contains the jdk.nashorn.api.scripting and jdk.nashorn.api.tree packages.
  • – contains the jjs tool.

6.2.2 Solaris and SPARC Ports

JEP 381 removes the source code and build support for the Solaris/SPARC, Solaris/x64, and Linux/SPARC ports. These ports were deprecated for removal in JDK 14 (JEP 362) with the express intent to remove them in a future release.

6.3 Reimplemented Feature

6.3.1 Legacy Datagram Socket API

DatagramSocket and MulticastSocket APIs were rebuilt with simpler and more modern implementations that are easy to maintain and debug. Therefore, the old design is a mix of legacy Java and C code that is painful to handle with.

The JEP 373 is a sequence of JEP 353, which already reimplemented the legacy Socket API. More details on how to use this feature can be found on Project Loom.

7. Summary

In this article, we could see all features presented in Java 15 release. Some features are very useful for developers such as Text Blocks, Records, Pattern Matching, and others are in the background of JVM like ZGC, Shenandoah and Foreign Access Memory. All this content is based on Oracle official Java blog, that you can find here.

8. Download the source code

You can download the full source code of this example here: Java 15 New Features Tutorial

Sergio Lauriano Junior

Sergio is graduated in Software Development in the University City of São Paulo (UNICID). During his career, he get involved in a large number of projects such as telecommunications, billing, data processing, health and financial services. Currently, he works in financial area using mainly Java and IBM technologies.
Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Newest Most Voted
Inline Feedbacks
View all comments
3 years ago

thank you

Back to top button