Java 15 is Generally Available (GA) – What’s New?

Java 15 became GA earlier this month (Sept 2020) (as announced by Oracle). As per Oracle’s now regular time-based schedule for major new releases of Java, this release was expected and comes 6 months after the previous one (Java 14 in March 2020). In this post I outline what I personally consider to be the most significant new features in Java 15 from a developer’s perspective, focusing primarily on the new Java language. I’ve also included some of the changes to the JDK core libraries / APIs and the JVM which will be of interest to developers.

TLDR; Java 15 is a relatively small, non-LTS release in terms of the total no. of enhancements (JDK Enhancement Proposals (JEPs)) it contains, and it only adds one, new language feature, which is in its first preview. Read on for more details.

1) New Language Features

1.1) Sealed Classes (First Preview)

There is one new language feature in Java 15, in its first preview – Sealed Classes. 

An author of a class or interface may want to restrict the classes which can extend (subclass or inherit from) it, for example to limit the impact of potential breaking changes in the future, or to avoid the need to write additional code to defend against unknown, future subclasses.

Prior to this new release developers could (and still can) achieve this in a couple of ways –

  • 1) You could prevent any class from extending your class by declaring it as final. 
  • 2) Or else you could limit the classes that can extend your class to all of those in the same package by either declaring the class, or all of its constructors package-private (the default when no accessor modifier is specified). However, this approach also places limits on what classes can access as well as extend from the class, which is often not the intention or an unintended side effect. 

The new Sealed Classes feature provides a new, third way for developers to restrict inheritance from a class or interface. It provides greater flexibility than the existing, second option mentioned above, by allowing you to specify an explicit list of permitted classes in the same package or module, rather than all of them, whilst not restricting access.

Syntax

The syntax for sealed classes extends the existing way of defining a class using two new reserved identifiers – sealed and permits. For example, class A can be declared as a Sealed class as follows – 
public sealed class A permits B, C, D { ... }

In this example, the compiler only allows classes B, C, and D to extend class A, and they must all be in the same package or module.

Each permitted sub-class must also have its inheritance capabilities explicitly specified.  In the above example:

  • Class B could be defined as final so that no further inheritance is allowed. (Final classes can now also be considered fully ‘sealed’ classes). 
  • Class C could itself be defined as sealed, permitting only a specific set of other named classes to inherit from it.
  • Class D could be defined as non-sealed e.g. public non-sealed class D { … } which reverts it to be open and allows any class to inherit from it. 

Although the JEP title is Sealed classes, this feature can be used for the inheritance of interfaces as well.

Goals of Sealed Classes

The obvious reason for the addition of Sealed classes  to Java is to provide authors of classes or interfaces with more control over how a class can be used as a superclass. 

However, they have also been introduced to support pattern matching for the switch statement in the future.  Sealed classes will make it possible for the compiler to perform additional checks on a switch statement that could remove the need to specify the ‘default’ case label in its body.

For more details of Sealed Classes see JEP 360.

1.2) Records (Second Preview)

JDK 15 includes a second (revised) preview of Records – the new language feature first previewed in the previous JDK 14 release which aims to provide a simpler and terser way to declare classes which are immutable data-structures (e.g. for use as Data Transfer Objects).

This second preview contains a few changes and clarifications, including the following.

Local Records (New)

This second preview introduces the new concept of local records.  These are similar in idea to local classes, enabling a record to be defined in a method and have its scope of use limited to that method. Not sure how often these will be needed.

Clarification – Implicitly Declared Fields are Final

One of the clarifications is “The implicitly declared fields corresponding to the record components of a record class are final and moreover are not modifiable via reflection (doing so will throw IllegalAccessException).” 

Clarification – How Annotations on Record Components are Used

The second preview also clarifies how annotations applied to record components  (the variables listed in the record definition) are used.

A record component represents several different concrete artefacts, specifically an instance variable, a constructor parameter and an accessor (getter) method with a return value of that type. If an annotation is applied to the record component, it will also be used in any of the concrete artefacts where applicable.  There is no way to restrict its use to a subset of where it can be used. Will this be sufficiently flexible? Time will tell.

1.3) Text Blocks are Now GA

Text Blocks (aka multiline strings) are not a new language feature for JDK 15, having first been previewed back in JDK 13, and having a second preview in JDK 14. However, as of JDK 15 they are no longer in preview, but now formally part of the Java language spec, as recognised by being included in the Java SE specification. The significance of this the feature can now be used without fear of changes to the API or behaviour. As I’ve discussed before I can see this feature being most useful e.g. for formatting multi line SQL statements in JDBC DAO, or for formatting chunks of markup (JSON, XML etc) in test code.

2) Enhancements to the Java Standard Library APIs

As is usual for a new JDK release, there have been a number of changes made to the Java SE (‘core’) library APIs.  I’ll focus on the noteworthy ones, and those that are of more interest to developers.

2.1) Edwards-Curve Digital Signature Algorithm (EdDSA)

A large proportion of the API changes are all contained in the java.security.spec and java.security.interfaces packages and relate to JEP 339: Edwards-Curve Digital Signature Algorithm. This is a new algorithm for implementing digital signatures that’s intended to provide additional security and better performance.

2.2) Other

Underlying implementations of the core library APIs continue to be refactored to address technical debt with a view to preparing for the introduction of Project Loom (aka virtual or ‘green’ threads). The latest refactoring in JDK 15 is the re-implementation of the legacy DatagramSocket API (JEP 373). 

Most of the other core library API changes are fairly minor and widely spread, e.g. 

  • CharSequence has a new method, isEmpty() 
  • etc.

3) Other New or Changed JDK Features

This section outlines other types of changes to the JDK, outside of the Java language and core libraries, e.g. in the JVM, that may be of interest to developers,

3.1) Shenandoah and ZGC Garbage Collectors now Production Ready

Recent JDK / Java releases have included two new low latency (pause time) garbage collectors – 

  • Oracle ZG –  first introduced in JDK 11 (see JEP 377
  • RedHat Shenandoah – first introduced in JDK 12 (see JEP 379).

These are now considered stable and robust enough to be promoted to production ready in JDK 15. 

It’s worth noting that these GCs are designed to support businesses that need ultra low latency CG – when pause time must be in low milliseconds – especially when using very large JVM memory heap sizes. These are niche use-cases and the use of these collectors come with trade-offs. . The overhead of using them is quite high in terms of CPU usage which will impact your application throughput. For most outfits, the default garbage collector, which continues to the G1 collector  in JDK 15, is the better choice, as it offers the best performance trade-offs for majority use-cases / app work loads.

3.2) Hidden Classes

Hidden classes (JEP 371) is an internal JVM feature rather than a language-level one, which the majority of developers won’t be concerned with. I only mention it here to clarify that it’s distinct from the Sealed Classes language language feature mentioned above.

4) Adoption Considerations

Before adopting JDK 15 in production, consider that Oracle has designated that it is not a long-term support (LTS) release. As a result, Oracle and most other JDK vendors, as has been the case in the past, will cease to provide maintenance (bug fixes and security patches) and offer support for this version of the JDK when the next version becomes available in 6 months time (JDK 16, due March 2021). If security and bug fixes are important to your business, and you don’t have the resources to commit to another upgrade to JDK 16 in six months time, then you may want to stick to using the current LTS release of the JDK (11) for your production apps. 

The next LTS release of Java – JDK 17 – isn’t due for another year (Sept 2021). In the meantime you can still test whether your existing apps are compatible with JDK 15, potentially shortening the timeline for upgrading LTS release used in production from JDK 11 to JDK 17 in the future.

5) Conclusion

Java 15 is a fairly small release. From a developer’s perspective, it only adds a single new language feature – Sealed Classes – which is not a feature that will be used in everyday development / coding, and it’s still in its first preview (so not suitable for production). Aside from that the API for Java Records is continuing to mature in its second preview, but again is not final yet. And Text Block (aka multiline strings) is now GA, and hence a safe bet for use in production (in terms of the API being stable).

Like other major Java releases, JDK 15 does contain a number of fixes and possible runtime performance improvements for the JVM. But it is still not a new  long-term support (LTS) release.

Given the above, my advice would be to defer adopting JDK 15 for your production apps. Also there is not much of anything new to try out in pre-production. 

Roll-on the next LTS release in a year’s time (JDK 17; Sept 2021) when we can all benefit from 3 years of enhancements since JDK 11, without sacrificing the availability of and commitments to long term support and maintenance.

Thanks.

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s