What is New in Java 17?

What is New in Java 17?

0 Comments

In September 2021, Java 17 was released as the latest LTS (long-term support) replacing Java 11. Now the big question is “What is new in Java 17?”

Java 17 has 14 JDK Enhancement Proposals (JEP) items. Out of those, there are 10 new features, 2 feature removals, and deprecation of 2 features.

In this post, I will cover the key new features of Java 17 applicable to application developers. I will also list the features that have been removed and the deprecated features.

New Features

Some of the key new features of Java 17 for application developers are:

  • Sealed classes and interfaces
  • Pattern matching for switch statements and expressions
  • New rendering pipeline for MacOS
  • New API for accessing large icons
  • Pseudo-Random Number Generators
  • New InstantSource Interface

Sealed Classes and Interfaces

Sealed classes and interfaces (JEP 409) restrict which other classes or interfaces can extend or implement them.

Note: Sealed classes and interfaces were a preview feature in Java 15.

Sealed classes use the permit keyword to specify the classes and interfaces that can extend or implement them.
Note that only sealed, final, and non-sealed classes can extend a sealed class.

Sealed classes restrict unnecessary class hierarchy. However, this is not the only motivation. Sealed classes allow you to provide an “escape hatch” for extension. This is the motivation for introducing non-sealed classes.

package com.example.geometry;

public abstract sealed class Shape
    permits Circle, Rectangle, Square {...}

public final class Circle extends Shape {...}

public sealed class Rectangle extends Shape {...}

public non-sealed class Square extends Shape {...}

In the above code snippet, Shape is a sealed class. This class permits extension by the Circle, Rectangle, and Square classes.

The code declares the Circle class as final and the Rectangle class as sealed.

The sealed Rectangle class can also permit other classes like this.

package com.example.geometry;

public abstract sealed class Shape
    permits Circle, Rectangle, Square {...}
public final class Circle extends Shape {...}

public sealed class Rectangle extends Shape 
permits TransparentRectangle, FilledRectangle {...}
public final class TransparentRectangle extends Rectangle {...}
public final class FilledRectangle extends Rectangle {...}
public non-sealed class Square extends Shape {...}

In the preceding code snippet, we have two final classes TransparentRectangle and FilledRectangle. Both the classes extend the sealed Rectangle class.

We also have a non-sealed Square class. This is the “escape hatch” implying unrestricted subclasses.

Note: One constraint of using a sealed class is that its permitted subclasses must belong to the same module. If it is declared in an unnamed module, it should be in the same package.

Pattern Matching for Switch

Java 17 introduces pattern matching for switch statements and expressions (JEP 406) as a preview feature.

Java 12 introduced switch expression as a Preview feature. Later, Java 14 standardized switch expression. Like any expression, switch expressions evaluate to a single value and can be used in statements. Switch expressions support “arrow case” labels eliminating the need for break statements to prevent fall through.

You can use pattern matching to test a switch expression against a number of patterns, each with a specific action. With pattern matching, you can express complex data-oriented queries concisely and safely.

This code shows a traditional switch statement . This statement prints the number of letters of elements present in a Status enum.

enum Status { OPEN, WIP, REVIEW,FIX, CLOSE; }

public class SwitchPatternMatching {
   public int numberOfLetters;
    public void printNumberOfLetters() {
        Status status = Status.CLOSE;
        switch (status) {
            case WIP:
            case FIX:
                numberOfLetters = 3;
                break;
            case OPEN:
                numberOfLetters = 4;
                break;
            case CLOSE:
                numberOfLetters = 5;
                break;
            case REVIEW:
                numberOfLetters = 6;
                break;
            default:
                throw new IllegalStateException("Invalid status: " + status);
        }
        System.out.println(numberOfLetters);
    }

The equivalent code in Java 17 is this.

public void printNumberOfLettersSwitchPattern() {
    Status status = Status.CLOSE;
    System.out.println(
    switch (status) {
        case WIP,FIX -> 3;
        case OPEN -> 4;
        case CLOSE -> 5;
        default ->throw new IllegalStateException("Invalid status: " + status);
    }
  );
}

The preceding code snippet directly returns the number of letters instead of storing it in some variable. Also, the code snippet does not have break statements to prevent fall through. This is a welcome update as break statements are error-prone and easy to forget.

In Java 17, you can also test null in switch directly, like this.

Status status = null;
  System.out.println(
  switch (status) {
      case null -> System.out.println("Encountered null!");
      case WIP,FIX -> 3;
      case OPEN -> 4;
      case CLOSE -> 5;
      default ->throw new IllegalStateException("Invalid status: " + status);
  }
);

Rendering Pipeline for MacOS

The Swing APIs use the Java 2D API for rendering. Prior to Java 17, rendering in MacOS is done using OpenGL APIs. In Java 17, you can use the new Apple Metal accelerated rendering API for macOS.

This is currently disabled by default. Therefore, rendering still uses OpenGL APIs, which are deprecated by Apple but still available.

To enable Metal, set this system property:

-Dsun.java2d.metal=true

As a programmer, your code won’t get affected. This is because Metal or OpenGL is transparent to applications. It is a difference in internal implementation and has no effect on Java APIs.

Note: The metal pipeline requires macOS 10.14.x or later. Earlier Operating System releases will ignore attempts to set the pipeline.

Accessing Large Icons

Java 17 brings a new API to the Swing library to access large icons.

The javax.swing.filechooser.FileSystemView.getSystemIcon(File, int, int) method is new in JDK 17. This method enables access to higher-quality icons.

Full implementation is there for the Windows platform. However, results on other platforms might vary and enhancement will happen later.

An example is this.

FileSystemView fsv = FileSystemView.getFileSystemView();
  Icon icon = fsv.getSystemIcon(new File("application.exe"), 64, 64);
  JLabel label = new JLabel(icon);

A common use case for this feature is to obtain a higher quality icon for an application executable (exe) file. This icon is suitable for creating a label that can be better scaled in a High DPI environment.

Enhanced Pseudo-Random Number Generators

Java 17 brings in new interface types and implementations for pseudorandom number generators (PRNGs). This new enhancement makes it easier to use various PRNG algorithms interchangeably in applications. It also provides streams of PRNG objects to support stream-based programming.

The API introduces the RandomGenerator, interface. This interface supplies a uniform API for all existing and new PRNGs. There are several specialized interfaces, such as SplittableRandomGenerator, JumpableRandomGenerator, LeapableRandomGenerator that extend RandomGenerator to provide specialized methods to generate pseudo-random numbers.

The new RandomGeneratorFactory class enables to locate and construct instances of RandomGenerator implementations.

The InstantSource Interface

Java 17 introduces a new InstantSource interface in the java.time package. This interface provides an abstraction of java.time.Clock that only focuses on the current instant and does not refer to the time zone. The primary purpose of this abstraction is to allow plugging in alternate instant sources as and when required.

You can initialize an object that requires the current instant during instantiation by passing an InstantSource into any method. A dependency injection framework, like Spring is one way to achieve this.

public class MyBean {
    private InstantSource source;  
//In Spring this can be autowired for dependency inhection
public MyBean(InstantSource source){
  this.source=source;
}
    ...
    public void process(Instant endInstant) {
      if (source.instant().isAfter(endInstant) {
        ...
      }
    }
  }

Removed Features

The two key features relevant to application developers that have been removed are:

  • Strongly Encapsulate JDK Internals: JDK comes with internal APIs that are not intended for external use. However, over the years the developers of various libraries, frameworks, tools, and applications have used internal elements of the JDK. Doing so can compromise both security and maintainability. These APIs include:
    • Some non-public classes, methods, and fields of java.* packages.
    • All classes, methods, and fields of sun.* packages.
    • Most classes, methods, and fields of com.sun.*jdk.*, and org.* packages.
  • RMI Activation: RMI Activation is an obsolete part of RMI. It has been optional since Java 8. This has been done because distributed systems are currently based on web technology. Moreover, there is evidence that very few existing applications use RMI Activation. In addition, maintaining RMI Activation comes with complexities and incurs continuing maintenance costs.

Deprecated Features

The key features relevant to application developers that have been deprecated are:

        • Applet API: Most web browser does not support Java browser plug-ins. Others have plans to stop support. Therefore, Java 17 has deprecated the Applet API for removal.
        • Security Manager: Deprecation of the Security Manager and APIs related to it. Java will remove them in a future release. The Java runtime issues a warning at startup if the Security Manager is enabled. You can disable the Security manager:
          • Through the command line using java -Djava.security.manager=disallow...
          • Programmatically using System::setSecurityManager.
  • Socket Implementation Factory Mechanism: Deprecation of the following static methods for setting the system-wide socket implementation factories:
    • static void ServerSocket.setSocketFactory​(SocketImplFactory fac)
    • static void Socket.setSocketImplFactory​(SocketImplFactory fac)
    • static void DatagramSocket.setDatagramSocketImplFactory​(DatagramSocketImplFactory fac)
  • DES and RC4 in Kerberos: The following Kerberos encryption types have been deprecated and disabled by default:
    • odes3-hmac-sha1
    • orc4-hmac

You as a developer can enable them by setting allow_weak_crypto = true in the krb5.conf configuration file.

  • JVM tool interface (JVM TI) Heap Functions: The following JVM TI functions have been deprecated:
    • IterateOverObjectsReachableFromObject
    • IterateOverReachableObjects
    • IterateOverHeap
    • IterateOverInstancesOfClass

A future release will update the preceding functions to return an error indicating that they are no longer supported.

Summary

The new Spring Framework 6 release is based on Java 17. Therefore, If you are a Spring developer, you should migrate to Java 17.

From a commercial point of view, Oracle has finally made Java 17 binaries free to use in production. It is also free to redistribute, at no cost, under the new “Oracle No-Fee Terms and Conditions” (NFTC) license. This move reverses a 2018 decision to charge for Oracle JDK production use.

In this post, I have only discussed the key points that Java 17 brings in. For the complete list, refer to the Release Note.

About SFG Contributor

Staff writer account for Spring Framework Guru

    You May Also Like

    Leave a Reply

    Your email address will not be published. Required fields are marked *

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