New features in Java 10

This article is targeted towards the recent development in the Java programming community, regarding the newest Java SDK update - the Java 10 update.

If you're a seasoned developer and follow the Java community, updates etc. you might think to yourself why did this update come so early? Java 9 was released just recently in January, to which a lot of developers still didn't migrate and a lot of people still don't use the Java platform module system, which is the main new feature of the previous development kit.

Novelties in Java 10

This JDK update features a lot of improvements and fixes in multiple functional areas of this language:

  1. Local-variable type inference
  2. Change in Java garbage collecting
  3. Root Certifications
  4. Garbage collector interface
  5. Experimental Java-based JIT compiler 
  6. Application class-data sharing
  7. Consolidating the JDK into a Single Repository
  8. Time-Based Release Versioning

Local-variable type inference is the biggest change in this update, at least visually - so let's start with explaining what it's all about.

 Local-variable type inference

This update has mixed feelings from a lot of developers, but has mostly been taken well since it was per the request of themselves that this update exists. It allows you to use the reserved word var to declare a local variable, without specifying its type at all. 

Note that var isn't a keyword in Java - it's a reserved word. This means that you can still use it as a variable name, a method name or a package name, but it's also important to notice that you can't use it as a class name. So this example compiles fine:

String var = "David";

One of the major "concerns" in Java is boilerplate code, and a lot of people complain about it. This was a step to reducing the amount of it. Even though I personally advocate strong-typed languages and the way it helps organize code, a lot of people don't find it that important and find using var more useful.

An example comparing the old and new options:

String name = "David";

var name = "David";


List list = new ArrayList<String>();

var list = new ArrayList<String>(); <-- Infers ArrayList<String>


Stream stream = list.stream();

var stream = list.stream(); <-- infers Stream<String>

These pairs of lines are effectively the same. The compiler will 'deduct' that the variable above is a String without you having to tell it. Additionally, we have some new rules when using vars.

1. We can't use var without initializing the variable. 

2. Compound declarations are forbidden

3. It's forbidden to initialize a null value for a var

With that in mind, the proceeding examples would result in a compiler error:

var name; <-- variable is not initialized
var i, j, k = 10; <-- compound declarations
var studentName = null; <-- initializing a null value


For some, it came as good news that this update isn't targeted at everything but rather restricted to:

  1.  Local variables with initializers
  2.  Indexes in the enhanced for loop
  3.  Locals declared in a traditional loop

This means that method parameters, constructor parameters, method return types, fields and catch formals won't apply this change. Also, this update won't affect old applications and code at all due to var being a reserved word rather than a keyword, as well as it being optional.

 Change in Java garbage collecting

This update also includes a change in the way Java garbage collecting works. The point of the update is to improve G1 latencies by making it full GC parallel in worst-case scenarios.

G1 was made the default garbage collector in Java 9. Oracle wanted to use a low-cost collector like G1 to improve experience and performance for most users instead of using the parallel garbage collecting system, which was default at the time.

G1 is designed to avoid full garbage collecting, and in fact, avoid full collections in general. This, however, can cause a problem because G1 in some cases can't reclaim memory fast enough for the application. To counter this, a fallback to full garbage collecting is called instead.

 Root certificates

This update might not have much meaning for people who aren't active members of OpenJDK. The goal of the update is to make OpenJDK more appealing and attractive to developers, as well as reduce the difference between OpenJDK builds and Oracle's JDK builds.

Oracle included a set of root certificates, which previously weren't included by default. This allows TLS and other critical security components to work by default.

 Garbage collector interface

This update will have meaning for more advanced developers and users of the JDK. The goal of this update is to make a clean interface for garbage collecting in order to improve modularity of different garbage collectors in the language. Additionally, Oracle has made it easier to remove a garbage collector from a JDK build and make it easier to add a new, perhaps even custom garbage collectors to the build.

 Experimental Java-based JIT compiler

This update enables the Java-based JIT compiler - Graal - to work as an experimental JIT (Just in Time) compiler of Linux. While Oracle certainly wanted to improve performance and speed issues that accompanied Java, both in writing and running, this update, in fact, isn't meant to beat the performance of already existing JIT compilers, but rather to test and debug it if needed.

Java 9 introduced us with an experimental AOT (Ahead of Time) compiler and Graal is the basis of it.

You can enable Graal now, as it is already in the JDK, as the JIT compiler by using the following options in the Java command line: 

-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler


 Application class-data sharing

The goal of this update is to improve the startup time of Java applications by reducing footprint and sharing common class metadata between different Java processes and also to extend Class-Data Sharing to allow archived classes to be loaded into custom class loaders.

Class-data sharing was introduced to us all the way back in JDK 5. It allows a certain set of classes to be pre-processed in a shared archive that can be memory-mapped during runtime to reduce startup time. Up until now, Class-data sharing only supported the bootstrap class loader to load archived classes. The update, however, allows the built-in system class loader, the built-in platform class loader, and custom class loaders to load archived classes instead.

To enable AppCDS (Application class-data sharing) use the following command in the command line:

XX:+UseAppCDS

This update is in a testing phase and hopefully will significantly improve space saving in the memory as well as significant startup time improvements.

 Consolidating the JDK into a Single Repository

The goal of this update is to merge all of the JDK repositories into a single repository to simplify and clean development.

For the majority of the time, the code base for the JDK was separated into eight different repositories:

  • root
  • corba
  • hotspot
  • jaxp
  • jaxws
  • jdk
  • langtools
  • nashorn

But why do it? Separation of concerns is widespread as the best solution to monolithic repositories and applications. Why would Oracle merge them into a single repository? In some cases, this approach poses more problems than the advantages it brings. This is such a case where it's not possible to perform an atomic commit across multiple repositories which all host the same source code. There were numerous examples where bugs spanned over multiple repositories, which made bug fixing really hard. There have been over 1100 bug ids which spanned over multiple repositories recorded, however, the actual number of these bugs is much higher since software engineers use separate bug ids. 

This was the main reason for the update, allowing engineers to perform atomic commits across repositories.

 Time-Based Release Versioning

The goal is to make it easier for developers to determine how old a release is, to allow them to decide if they'll update to the newer release whether it be for security fixes or additional features.

Also, this novelty will lay out concisely which release will have short-term support, and which releases will have long-term support. Oracle will from now on release new builds of the JDK every 6 months, which means that Java 11 will be released in September of 2018. 

Here's a small table of previous releases, as well as upcoming releases:

Release   GA DatePremier Support until
Extended Support until 
Sustaining Support until
Java 6
Dec 2006 
Dec 2015
Dec 2018
 Indefinite
Java 7
Jul 2011
Jul 2019 
Jul 2022 
Indefinite 
Java 8
Mar 2014 
Mar 2022
 Mar 2025 
Indefinite 
Java 9 (non-LTS)
  Sep 2017 
Mar 2018 
Not Available
Indefinite 
Java 10 (18.3)(non-LTS)
 Mar 2018 
Sep 2018 
Not Available 
Indefinite 
Java 11 (18.9)(LTS) 
Sep 2018 
Sep 2023 
Sep 2026
Indefinite


Both Java 9 and Java 10 are non-LTS which means that they have Premier Support until the release of the next JDK and don't have Extended Support. On the other hand, Java 11 has Long-Term Support with Premier Support until 2023 and extended Support until 2026.

If Oracle sticks to the plan, we could be expecting a new JDK in March 2019.

Conclusion

All in all, Oracle really put effort into fixing performance and speed issues in Java, as well as reducing boilerplate code. This is a good sign, as it means that the company is listening to developers as well as the needs of modern software engineering. With all of the things announced for Java 11 (which I might cover in another blog), Java's future is looking bright and prosperous. 

I covered what I believe were the most prominent and important changes, and skipped those which didn't concern most people. If you'd like to read the official JEP list and documentation on OpenJDK, you can do so here.