New Features in Java 12

Rajesh kumar
10 min readMar 14, 2019

The final release of Java 12 is coming on March 19th, 2019, however there is an early access of Java 12 available now to download. Let’s start with the Java 12 release schedule and then explore each of the features at a high level.

Release Schedule:
2018/12/13 -Rampdown Phase One (fork from main line)
2019/01/17 -Rampdown Phase Two
2019/02/07 -Release-Candidate Phase
2019/03/19 -General Availability

New Features in Java 12:

1)Switch Expressions (Preview)
2)Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)
3)Microbenchmark Suite
4)JVM Constants API
5)One AArch64 Port, Not Two
6)Default CDS Archives
7)Abortable Mixed Collections for G1
8)Promptly Return Unused Committed Memory from G1

1)Switch Expressions (Preview): Switch statement has been around from starting of Java and the current design of switch statement closely fellows languages like C, C++ in its syntax and semantics with this there some drawbacks where some boiler plate code exist like repetition of break statement, which often masks developers in hard to debug errors when there is a missing of break statement and sometimes your business logic itself repeats , with the new version of Java this has been addressed. For example, if we think of business use case like where you need provide the discount to every customer based on the day the customer visited to your shop like TUESDAY, WEDNESDAY, THURSDAY with 10%. for MONDAY, Friday 15% and SATURDAY, SUNDAY with 20% with the existing switch it looks something like below

With the New Switch the same program can be written as below

The code to the right of a “case L ->” switch label is restricted to be an expression, a block, or a throw statement.
In new version switch is available as an expression and also as a statement. Let’s step back a little into the basics to difference between this 2. There are multiple difference between the expression and the statement one of the main one is a Statement is an operation which gets executed and doesn’t return any value after the completion of operation whereas for Expression after the completion of the operation a value is return to the caller. The above example can be re-written as below

As the switch Expression is available as preview feature its need to be compiled by enabling preview features of Java as below

To run the program

2)Shenandoah: A Low-Pause-Time Garbage Collector: With Java 12 we have another GC which is available with Java 12 as experimental with Java 11 we had ZGC as experimental which is still experimental with Java 12. Shenandoah GC was developed by Red hat and is now available as open source with JDK12. The main goal of Shenandoah is to decrease the pause time. This is quite similar to G1GC with concept of regions, but the beauty of the Shenandoah GC comes with executing concurrently each task there by decreasing the pause time with this now the GC pause time doesn’t depend on the size of the heap whether its 2GB or 10 GB its same. Shenandoah GC at high level does 4 activities where each of the activity as set of tasks during its GC cycle

a) Mark

b) Evacuation

c)Update Reference

d)Cleanup

a) Mark : In this phase the GC starts the concurrent marking of object for reclaiming of memory by starting the scan from the root set and walks over heap , during this all the regions are scanned concurrently and objects are marked for deletion. There are 3 tasks in this process

i)Init mark: Initiates the concurrent marking. It prepares the heap and application threads for concurrent mark

ii)Concurrent mark: walks over the heap, and traces reachable objects. This phase runs alongside the application, and its duration is dependent on the number of live objects and the structure of object graph in the heap.

iii)Final mark: finishes the concurrent marking by draining all pending marking/update queues and re-scanning the root set. It also initializes evacuation by figuring out the regions to be evacuated (collection set), pre-evacuating some roots, and generally prepares runtime for the next phase.

b) Evacuation: Once the marking is completed and initializing of evacuation done in the previous step final mark now GC evacuation activity starts. This operation is concurrent where the Objects in the region are copied to the new region. with Concurrent Evacuation the objects now have new reference location.

i)Concurrent Evacuation: This is the major difference against other OpenJDK GCs. This phase is again running along with application, and so application is free to allocate. Its duration is dependent on the size of chosen collection set for the cycle.

c) Update Reference: After Evacuation activity is completes the next activity GC does is updating of the Reference for the new object which are copied into new region during the Evacuation. The process is also done concurrently where it works on multiple regions in updating. This activity has 3 tasks

i)Init Update Ref: Initializes the update references phase. It does almost nothing except making sure all GC and applications threads have finished evacuation, and then preparing GC for next phase. This is the third pause in the cycle, the shortest of them all.

ii)Concurrent Update References: Walks over the heap, and updates the references to objects that were moved during concurrent evacuation. This is the major difference against other OpenJDK GCs. Its duration is dependent on number of objects in heap, but not the object graph structure, because it scans the heap linearly. This phase runs concurrently with the application.

iii)Final Update Refs: Finishes the update references phase by re-updating the existing root set. It also recycles the regions from the collection set, because now heap does not have references to (stale) objects to them. This is the last pause in the cycle, and its duration is dependent on the size of root set.

d) Cleanup: In this activity the GC used to reclaim the regions which are unused by any object this activity is also performed concurrently and this task is triggered 2 times in the GC cycle Firstly just after the Marking is completed during this Cleanup reclaims immediate garbage regions — that is, the regions where no live objects are present, as detected after the concurrent mark. and secondly once the Update of Reference task happens during this Cleanup reclaims the collection set regions, which now have no references to.

Below is the regular Shenandoah GC cycle looks like this:

Sample Test Results:

3)Microbenchmark Suite: With this release, JDK source code now comes with a microbenchmark suite this release is the initial start for microbenchmark, which allows developers to run existing microbenchmarks and create new ones and with this release it has implement for Java base module for packages io, lang, math, net, security, util.(an initial set of around a hundred benchmarks in the suite). The microbenchmarks are done using the toolkit JMH (Java Microbenchmark Harness). JMH is developed by the same people who implement the Java virtual machine. With microbenchmark suite we can start measuring the performance on different versions of JDK with the further release the suite size will be growing allowing us to get more insight and it also allows us to execute even partially set of benchmarks without mandating to execute the complete set.

The following directory structure is proposed:

jdk/jdk

…/make/test (Shared folder for Makefiles)

…/test (Shared folder for functional tests)

…/micro/org/openjdk/bench

…/Java (subdirectories similar to JDK packages and modules)

…/vm (subdirectories similar to HotSpot components)

First time to Microbenchmark ? Here is just a quick overview of it for first timers.

Microbenchmarking is measuring the performance of some small code fragment. This are mostly written when you wanted to identify the piece of code which eats up your resources in your application. writing the microbenchmark is a bit tricky as JVM may apply optimizations to your components when executed inside the benchmark which could not have been applied if the component was executed inside your real application. Such optimizations will make your code look faster than it will be in reality, the other aspects are Loop Optimization, Dead Code Elimination.

Java Microbenchmark Harness in short as JMH is a toolkit that helps you implement Java microbenchmarks correctly. Below is a quick setup to kick start on JMH

Setup : Run the below maven command to quickly setup your project.

Writing your First program: Once the setup is done you will be having MyBenchmark.Java update the test method to write your code

Running your code: To run your code execute below command which create the jar file under the target folder of your project.

mvn clean install

Run your microbenchmark :

java -jar target/myfirst-benchmark.jar

4)JVM Constants API: Every Java class file has a constant pool which stores the operands for bytecode instructions in the class. Broadly speaking, entries in the constant pool describe either run-time artifacts such as classes and methods, or simple values such as strings and integers. All these entries are known as loadable constants because they may serve as operands for the ldc instruction (“load constant”). They may also appear in the static argument list of a bootstrap method for the invokedynamic instruction. Executing an ldc or invokedynamic instruction causes the loadable constant to be resolved into a “live” value of a standard Java type such as Class, String, or int. This release Introduce an API to model nominal descriptions of key class-file and run-time artifacts, in particular constants that are loadable from the constant pool.

5)One AArch64 Port, Not Two: In JDK today there are Two 64-bit ARM ports exist. The main sources for these are in the src/hotspot/cpu/arm and open/src/hotspot/cpu/aarch64 directories. Although both ports produce aarch64 implementations to obey according to JEP 340. So with this release there have removed the one which was contributed by Oracle as arm64 while retaining 32 bit ARM port and the 64-bit aarch64 port.

6)Default CDS Archives: This is an Enhancement to the JDK build process to generate a class data-sharing (CDS) archive, using the default class list, on 64-bit platforms. Which will improve start up time eliminating the need for users to run -Xshare:dump to benefit from CDS. Numerous enhancements have been added to the base CDS feature since JDK 8u40. The startup time and memory sharing benefits provided by enabling CDS have increased significantly. Measurements done on Linux/x64 using JDK 11 early-access build 14 show a 32% startup time reduction running HelloWorld. On other 64-bit platforms, similar or higher startup performance gains have been observed. Currently, a JDK image includes a default class list, generated at build time, in the lib directory. Users who want to take advantage of CDS, even with just the default class list provided in the JDK, must run Java -Xshare:dump as an extra step. This option is documented, but many users are unaware of it.

7)Abortable Mixed Collections for G1 : This is one of the feature enhancement in this release made to G1 GC Making G1 mixed collections abortable if they might exceed the pause target . One of the goals of G1 is to meet a user supplied pause time target for its collection pauses. G1 uses an advanced analysis engine to select the amount of work to be done during a collection (this is partly based on application behavior). The result of this selection is a set of regions called the collection set. Once the collection set has been determined and the collection has been started then G1 must collect all live objects in all regions of the collection set without stopping. This behavior can lead to G1 exceeding the pause time goal if the heuristics choose a too-large collection set, which for example can happen if the application’s behavior changes such that the heuristics work on “stale” data. This can be observed during mixed collections, where the collection set can often contain too many old regions. There is need for a mechanism that detects when the heuristics repeatedly select a wrong amount of work for collections, and if so, have G1 perform the collection work incrementally in steps, where the collection can be aborted after each step. Such a mechanism would allow G1 to meet the pause time goal more often.

8)Promptly Return Unused Committed Memory from G1: This is another feature enhancement in this release made to G1 GC Making G1 garbage collector to automatically return Java heap memory to the operating system when idle. Currently the G1 garbage collector may not return committed Java heap memory to the operating system in a timely manner. G1 only returns memory from the Java heap at either a full GC or during a concurrent cycle. Since G1 tries hard to completely avoid full GCs, and only triggers a concurrent cycle based on Java heap occupancy and allocation activity, it will not return Java heap memory in many cases unless forced to do so externally. This behavior is particularly disadvantageous in container environments where resources are paid by use. Even during phases where the VM only uses a fraction of its assigned memory resources due to inactivity, G1 will retain all of the Java heap. This results in customers paying for all resources all the time, and cloud providers not being able to fully utilize their hardware. If the VM were able to detect phases of Java heap under-utilization (“idle” phases), and automatically reduce its heap usage during that time both would benefit. To accomplish the goal of returning a maximum amount of memory to the operating system, G1 during inactivity of the application, periodically try to continue or trigger a concurrent cycle to determine overall Java heap usage. This will cause it to automatically return unused portions of the Java heap back to the operating system.

--

--