JDK 12: The new features in Java 12

Java 12 arrives with switch expressions to improve coding and allow pattern matching, and raw string literals to simplify multiline expressions

JDK 12: The new features in Java 12
Couleur (CC0)

The production release of Java Development Kit 12, based on Java SE (Standard Edition) 12, is now available. JDK 12 builds are available from Oracle for Linux, Windows, and MacOS. 

Where to download JDK 12

You can download the JDK 12 from the Java.net website.

Open source builds are provided under the GNU General Public License v2, with Classpath Exception. Commercial builds of JDK 12 from Oracle can be found on the Oracle Technology network under a non-open source license.

New features in Java 12

Shenandoah garbage collector

Java 12 adds Shenandoah, an experimental garbage-collection algorithm, to reduce garbage-collection pause times by performing evacuation work concurrently with running of Java threads. Shenandoah provides an appropriate algorithm for applications that value responsiveness and predictable short pauses. The intent is not to fix all JVM pause issues, however.

Red Hat currently supports Shenandoah on the Aarch64 and AMD64 architectures.

Abortable mixed collections for the G1 garbage collector

Java 12 makes G1 mixed collections abortable if they might exceed the pause target. A goal of G1 was to meet a user-supplied pause time target for its collection pauses.

Previously, an advanced analysis engine selected the amount of work to be done during a collection. The result was a set of regions known as the collection set. Once the set had been determined and collection started, G1 collected all live objects in the regions of the collections in all regions without stopping. But this could lead to G1 exceeding the pause-time goal if an application’s heuristics chose a collection set that was too large.

A mechanism was needed to detect when heuristics repeatedly selected an incorrect amount of work for collections and, if this happened, have G1 perform collection work incrementally in steps, where the collection could be aborted after each step. The mechanism introduced in Java 12 enables G1 to meet the pause time goal more often.

Prompt return of unused committed memory

Java 12 enhances G1 to automatically return Java heap memory to the operating system when idle. This memory is released in a reasonable period of time when there is very low application activity.

Previously, G1 only returned memory from the heap at either a full garbage-collection or during a concurrent cycle. With G1 trying to avoid full garbage collection, only triggering a concurrent cycle based on heap occupancy and allocation activity, it would not return heap memory in many cases unless forced to do so externally. This behavior was disadvantageous in container environments where resources are paid by use. Even when the JVM uses only a fraction of its assigned memory due to inactivity, G1 retained the full heap. So, customers paid for all resources all the time, and cloud providers could not make full use of their hardware.

With Java 12, the JVM can detect phases of heap underutilization and automatically reduce its heap usage during that time. 

JVM constants API

This API models nominal descriptions of key-class file and runtime artifacts, particularly constants loadable from the constant pool. Java 12 defines a family of value-based symbolic reference types in a new package, java.lang.invoke.constant, to describe each kind of loadable constant.

Constant pools exist in every Java class, storing operands and bytecode instructions in the class. Entries in the constant pool describe either runtime artifacts such as classes and methods or simple values such as strings and integers. These entries are known as loadable constants.

Programs that manipulate class files must model bytecode instructions and in turn loadable constants. But using standard Java types to model loadable constants is inadequate. This may be acceptable for a loadable constant that describes a string, but it is problematic for a loadable constant that describes a class, because producing a “live” Class object relies on the correctness and consistency of class loading. Class loading, however, has many environmental dependencies and failure modes.

So, programs that deal with loadable constants could be simplified if they could manipulate classes and methods and lesser-known artifacts such as method handles and dynamically computed constants in a nominal, symbolic form. Thus the JVM constants API gives libraries and tools a single, standard way to describe loadable constants.

Improved startup, CDS, and garbage collection

Java 12 enhances the JDK build process to generate a default class data-sharing (CDS) archive, using the default class list, on 64-bit platforms. This improves out-of-the-box startup time and eliminates the need to run -Xshare:dump to benefit from the CDS. The JDK build process has been modified to run java-xshare:dump after linking the image.

Additional command-line options have been included to fine-tune garbage-collection heap times to improve memory layout for common cases. Users with more advanced requirements, such as custom class lists that include application classes and different garbage-collection configurations, are still able to create a custom CDS archive.

Reduced number of ARM ports

Java 12 removes all sources related to the arm64 port while retaining the 32-bit ARM and 64-bit aarch64. Removal of this port would let contributors focus efforts on a single 64-bit ARM implementation and eliminate duplicate work that would result from maintaining two ports. Currently, two 64-bit ARM ports are in the JDK.

Switch expressions

Switch expressions simplify coding by extending the switch statement so it can be used as either a statement or an expression. This enables both statements and expressions to use either “traditional” or “ simplified” scoping and control flow behavior. These changes result in simpler “everyday” coding and prepare the way for use of pattern matching in switch.

As Java builders move to support pattern matching, irregularities of the Java switch statement have become impediments. These include the default control flow behavior of switch blocks; default scoping of switch blocks, in which the block is treated as one single scope; and switch working only as a statement. The current design of Java’s switch statement closely follows languages such as C++ and, by default, supports fallthrough semantics. This control flow has been useful for writing low-level code. But when switch is used in higher-level contexts, its error-prone nature begins to outweigh the flexibility.

Basic benchmark suite

JDK 12 includes a basic suite of microbenchmarks, which have been added to the platform’s source code. The goal is to make it easier for developers to run existing benchmarks or build new ones.

The microbenchmarks suite proposal, created in July 2014 and updated in early November 2018, was underpinned by the Java Microbenchmark Harness (JMH), for building benchmarks written in Java and other JVM languages. The suite is colocated with JDK source code in a single directory, with developers able to easily add new benchmarks.

It was not a goal to provide benchmarks for new JDK features or create a complete set of benchmarks covering everything in the JDK. Also note that the benchmarking suite is not required for regular JDK builds but is a separate build target. 

The proposal called for the creation of a new page on wiki.openjdk.java.net to explain how to develop benchmarks and describe requirements. These requirements will mandate adherence to coding standards, reproducible performance, and documentation.

JDK 12 updates

Plans call for JDK 12 to receive two updates before being succeeded by JDK 13 in six months. JDK 12 is part of Oracle’s six-month release cadence introduced with JDK 9 in September 2017.  JDK 12 is characterized as a feature release, unlike JDK 11, which is a long-term support release with several years of support planned.

Copyright © 2019 IDG Communications, Inc.