Java 14

created onJuly 16, 2022

general availability on 2020-03-17

JEPs

new features

JEP state summary /remark
JEP 305: Pattern Matching for instanceof (Preview) preview instanceof now saves you from explicit, verbose casts.
JEP 343: Packaging Tool (Incubator) incubator create a tool for packaging self-contained Java applications, supporting native packaging formats to give end users a natural installation experience.
JEP 349: JFR Event Streaming standard expose JDK Flight Recorder data for continuous monitoring.
JEP 352: Non-Volatile Mapped Byte Buffers standard add new JDK-specific file mapping modes so that the FileChannel API can be used to create MappedByteBuffer instances that refer to non-volatile memory. With NVM, it is possible to create and update program state across program runs without the significant translation costs that persistent media normally imply.
JEP 358: Helpful NullPointerExceptions standard NPE messages are now more specific about the cause than just listing the line number of the code where the unlucky consumer is.
JEP 359: Records (Preview) preview a new kind of restricted class for data containers without boiler code.
JEP 361: Switch Expressions standard extended switch statement that can be used as either a statement or an expression. both forms can use either a “traditional” or “simplified” scoping and control flow behavior. see comments on ‘JEP 325: Switch Expressions (Preview)'
JEP 364: ZGC on macOS (Experimental) experimental macOS port of the ZGC garbage collector.
JEP 365: ZGC on Windows (Experimental) experimental Windows port of the ZGC garbage collector.
JEP 368: Text Blocks (Second Preview) second preview add text blocks to the java language. 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. see comments on ‘JEP 355: Text Blocks (Preview)'
JEP 370: Foreign-Memory Access API (Incubator) incubator an API to allow Java programs to safely and efficiently access foreign memory outside of the Java heap. Applications include sharing memory across multiple processes, and serialization / deserialization of memory content by mapping files into memory (via, e.g., mmap).

JDK internal

JEP summary /remark
JEP 345: NUMA-Aware Memory Allocation for G1 improves G1 performance on large machines by implementing NUMA-aware memory allocation.

deprecated

JEP summary /remark
JEP 362: Deprecate the Solaris and SPARC Ports deprecate the Solaris/SPARC, Solaris/x64, and Linux/SPARC ports, with the intent to remove them in a future release.
JEP 366: Deprecate the ParallelScavenge + SerialOld GC Combination deprecate the combination of the Parallel Scavenge and Serial Old garbage collection algorithms. It is not a goal to remove this GC combination.

removed

JEP summary /remark
JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector remove the Concurrent Mark Sweep (CMS) garbage collector.
JEP 367: Remove the Pack200 Tools and API remove the pack200 and unpack200 tools, and the Pack200 API in the java.util.jar package. These tools and API were deprecated for removal in Java SE 11 with the express intent to remove them in a future release.

some feature details

JEP 305: Pattern Matching for instanceof (Preview)

You can now save the explicit cast after an test with code like this:

if (obj instanceof String s) { // can use s here } else { // can't use s here }

If obj is an instance of String, then it is cast to String and assigned to the binding variable s. The binding variable is in scope in the true block of the if statement, and not in the false block of the if statement.

The scope of the binding variable is determined by the semantics of the containing expressions and statements. For example, in the following code, the s in the true block refers to a field in the enclosing class, and the s in the false block refers to the binding variable introduced by the instanceof operator:

if (!(obj instanceof String s)) { s.contains(..) } else { s.contains(..) }

For more complex conditionals than a single instanceof, the scope of binding variale grows accordingly:

if (obj instanceof String s && s.length() > 5) { ... }

here, s is in the scope of the right hand side of the operator and in the scope of the true block, if the instanceof succeeds (if the instanceof fails, the short-circuits and the right hand side of is not executed).

If we replace the operator with the operator:

if (obj instanceof String s || s.length() > 5) { ... }

s is neither in the scope of the right hand side of the operator, nor in the scope of the true block. Instead, s at these points refers to a field in the enclosing class.

The pattern will only match, and s will only be assigned, if obj is not null.

JEP 343: Packaging Tool (Incubator)

The jpackage tool packages a Java application into a platform-specific package that includes all of the necessary dependencies. The application may be provided as a collection of ordinary JAR files or as a collection of modules. The supported platform-specific package formats are:

  • Linux: deb and rpm
  • macOS: pkg and dmg
  • Windows: msi and exe

By default, jpackage produces a package in the format most appropriate for the system on which it is run.

jpackage will not support:

The following features of the javapackager tool will not be supported:

  • no support of jdeps for determining required modules
  • no support for the Ant plugin
  • no support for cross compilation. I.e., in order to create Windows packages one must run the tool on Windows. The packaging tool will depend upon platform-specific tools.
  • no special support for legal files beyond what is already provided in JMOD files. There will be no aggregation of individual license files.
  • no native splash screen support.
  • no auto-update mechanism.
  • no GUI for the tool but only a CLI (command-line interface)
  • no Java Web Start application support
  • no supprt for JavaFX-specific features
  • the tool will not be available on Solaris.

packaging non-modular app from jars

For an app composed of JAR files, all in a directory named lib, with a file lib/main.jar containing the main class, run:

jpackage --name myapp --input lib --main-jar main.jar

will package the application in the OS’ default format, leaving the resulting package file with an OS specific name (i.e., myapp.exe on Windows) in the current directory. The name of the package will be myapp. The package will include a launcher for the application, also called myapp. To start the application, the launcher will place every JAR file that was copied from the input directory on the class path of the JVM.

If the MANIFEST.MF file in main.jar does not have a Main-Class attribute then you must specify the main class explicitly on the command line:

jpackage --name myapp --input lib --main-jar main.jar --main-class myapp.Main

packaging modular apps

For a modular app, composed of modular JAR files and/or JMOD files in a lib directory, with the main class in the module myapp, run:

jpackage --name myapp --module-path lib -m myapp

If the myapp module does not identify its main class then, again, you must specify that explicitly on the command line:

jpackage --name myapp --module-path lib -m myapp/myapp.Main

package metadata

The jpackage tool allows you to specify various kinds of metadata for your package.

Options common to all platforms are:

  • –app-version
  • –copyright
  • –description
  • –license-file
  • –name
  • –vendor

JEP 359: Records (Preview)

From the JEP:

" It is not a goal to declare "war on boilerplate" "
JEP 359: Records, Non-Goals

😁​😁​😁​

A record has a name and a state description. Optionally, records can have a body:

record Coordinate(double lat, double lon)

The state description in the code above declares the components of the record.

A record acquires many standard members automatically:

  • a private final field for each component of the state description.
  • a public read accessor method for each component of the state description, with the same name and type as the component, aka a getter for the component.
  • a public constructor, whose signature is the same as the state description, which initializes each field from the corresponding argument.
  • implementations of equals and hashCode that say two records are equal if they are of the same type and contain the same state.
  • an implementation of toString that includes the string representation of all the record components, with their names.

You can explicitly declare members of a record:

record Person(String name, int age) { public Coordinate { if (age < 0) // implicit constructor parameter throw new IllegalArgumentException("nope"); } }

A record has the following restrictions:

  • can not extend any other class.
  • can not declare instance fields other than the private final fields which correspond to components of the state description. Any other fields which are declared must be static.
  • are implicitly final.
  • can not be abstract.
  • the components of a record are implicitly final. This restriction embodies an immutable by default policy.

Apart from that, records are like ordinary classes:

  • can be declared top level or nested
  • can be generic
  • can implement interfaces
  • are instantiated via the new keyword
  • the record’s body may declare static methods, static fields, static initializers- constructors, instance methods, and nested types.
  • the record, and the individual components in a state description, may be annotated

Nested records are implicitly static (this avoids an immediately enclosing instance which would silently add state to the record).

reference

OpenJDK JDK 14 feature list and schedule

JEP 305: Pattern Matching for instanceof (Preview)
JEP 343: Packaging Tool (Incubator)
JEP 359: Records (Preview)