JAVA-RELEASE/JAVA-15

Java 15: Feature and Highlights

This article covers features of Java 15 with code examples

Pravinkumar Singh
5 min readJun 26, 2023

Java 15, released in September 2020, brought a host of new features and enhancements. Here’s a list of the most notable features included in Java 15, with Java code examples.

Sealed Classes (JEP 360)

Sealed classes and interfaces restrict which classes can inherit from them or which classes can implement the interface. Controlling the inheritance hierarchy can lead to clearer and better-maintained codebases.

Example: In an application that interprets mathematical expressions, you can use sealed classes to define limited hierarchies:

public sealed abstract class Expr
permits ConstantExpr, PlusExpr, TimesExpr, NegExpr {}

public final class ConstantExpr extends Expr {
private final int i;

public ConstantExpr(int i) {
this.i = i;
}

public int getValue() {
return i;
}
}

public final class PlusExpr extends Expr {
private final Expr a, b;

public PlusExpr(Expr a, Expr b) {
this.a = a;
this.b = b;
}

public Expr left() { return a; }
public Expr right() { return b; }
}

public final class TimesExpr extends Expr {
private final Expr a, b;

public TimesExpr(Expr a, Expr b) {
this.a = a;
this.b = b;
}

public Expr left() { return a; }
public Expr right() { return b; }
}

public final class NegExpr extends Expr {
private final Expr e;

public NegExpr(Expr e) {
this.e = e;
}

public Expr expr() { return e; }
}

The code above defines Expr subclasses so you can prevent extensibility and guarantee that code handling Expr types won't encounter unexpected subclasses.

Pattern Matching for instanceof (Second Preview, JEP 375)

Pattern matching simplifies the use of instanceof by combining type-checking, casting, and assignment into a single operation. It results in more concise and readable code.

Example: Pattern matching can simplify the handling of multiple types in a sum or tagged union type:

public void processShape(Shape shape) {
if (shape instanceof Rectangle r) {
System.out.println("Processing Rectangle of area " + r.getWidth() * r.getHeight());
} else if (shape instanceof Circle c) {
System.out.println("Processing Circle of area " + Math.PI * Math.pow(c.getRadius(), 2));
} else if (shape instanceof Triangle t) {
//...
} else {
throw new IllegalArgumentException("Unknown shape");
}
}

This code eliminates manual casting. It’s more readable and makes handling sum types or discriminated unions more efficient.

Text Blocks (Standardized, JEP 378)

Text blocks simplify the creation and maintenance of multi-line string literals, reducing the need for complicated string concatenation.

Example: SQL Queries

String sqlQuery = """
SELECT firstName, lastName
FROM users
WHERE country = 'USA'
AND age > 25
""";

// Execute SQL query...

Here, text blocks make it easier to represent a multi-line SQL query compared to concatenating individual strings.

Hidden Classes (JEP 371)

Hidden classes are classes generated at runtime that are not discoverable via reflection. They are intended for frameworks that generate classes for internal use, such as interacting with user-defined code.

Use-case Scenario: In a Dynamic proxy factory, hidden classes can be generated for specific interfaces in compliance with the contract:

    public static <T> T createProxy(Class<T> interfaceType) {

// Load implementation from a configuration file
Class<?> hiddenImplClass = /* Load hidden class generated at runtime for the interface type */;

// Instantiate hiddenImplClass
T hiddenImpl = /* Create instance of hiddenImplClass, e.g., using hiddenClass.getDeclaredConstructor().newInstance() */;

// Return instance of hiddenImplClass as interfaceType
return interfaceType.cast(hiddenImpl);
}

This code snippet demonstrates how a proxy factory can generate hidden classes for specific interfaces at runtime, allowing it to comply with an interface contract without exposing implementation details.

Edwards-Curve Digital Signature Algorithm (JEP 339)

The Edwards-Curve Digital Signature Algorithm (EdDSA) is a modern, high-performance signing algorithm that provides better security and performance compared to traditional signature algorithms, like RSA and DSA.

Example: Secure Communication in a Client-Server Model, Consider a client-server model in which communications are required to be secure. You may use the EdDSA for signing and verifying messages to ensure they’re authentic and haven’t been tampered with.

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.util.Base64;

public class EdDSASignatureExample {
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EdDSA");
KeyPair keyPair = keyPairGenerator.generateKeyPair();

// Sign a message
String message = "Confidential message";
byte[] signature = signMessage(message, keyPair.getPrivate());
String encodedSignature = Base64.getEncoder().encodeToString(signature);

// Verify the signed message
boolean isValid = verifyMessage(message, encodedSignature, keyPair.getPublic());
System.out.println("Is the signature valid? " + isValid);
}

public static byte[] signMessage(String message, PrivateKey privateKey) throws Exception {
Signature sig = Signature.getInstance("EdDSA");
sig.initSign(privateKey);
sig.update(message.getBytes(StandardCharsets.UTF_8));
return sig.sign();
}

public static boolean verifyMessage(String message, String encodedSignature, PublicKey publicKey)
throws Exception {
byte[] signature = Base64.getDecoder().decode(encodedSignature);
Signature sig = Signature.getInstance("EdDSA");
sig.initVerify(publicKey);
sig.update(message.getBytes(StandardCharsets.UTF_8));
return sig.verify(signature);
}
}

The example above demonstrates signing and verifying a message using the EdDSA algorithm.

Remove the Nashorn JavaScript Engine (JEP 372)

The Nashorn JavaScript Engine has been removed from Java 15. Developers are encouraged to use alternative engines like GraalVM, which provides more modern JavaScript features.

Use-case Scenario: Embedding a JavaScript Engine with GraalVM, For applications that require JavaScript code to be executed alongside Java, GraalVM can be used as an alternative to Nashorn.

import org.graalvm.polyglot.*;

public class GraalVMExample {
public static void main(String[] args) {
try (Context context = Context.create()) {
// Run JavaScript code
context.eval("js", "console.log('Hello, GraalVM JavaScript!')");
}
}
}

Disable and Deprecate Biased Locking (JEP 374)

Biased locking has been disabled by default and deprecated in Java 15. This primarily affects JVM users rather than developers writing code, since it pertains to a JVM optimization technique that has become less relevant for modern hardware.

ZGC: A Scalable Low-Latency Garbage Collector (JEP 377)

ZGC is a garbage collector that can improve the performance of applications with large heaps and many processor cores. It is now available on macOS and Windows platforms, after previously being introduced on Linux.

Example: You may enable the ZGC garbage collector by adding the following JVM option when running your Java application:

java -XX:+UseZGC MyApplication

Deprecate RMI Activation for Future Removal (JEP 385)

The RMI Activation system has been deprecated in Java 15, with plans to remove it in future JDK releases. For developers who rely on RMI, Java offers a range of modern alternatives to RMI Activation, such as Java’s built-in WebSocket support or external libraries like gRPC Java and Apache Thrift.

Conclusion

Overall, this version of Java introduces some interesting features such as sealed & hidden classes, and optimization of existing features. Hope you like it.

Peace!

Related reads : java-release

--

--