Java 10 Features

Java 10 was released on March 20, 2018, The JDK 10 is an implementation of JAVA SE 10. As we know, Java is slow in growth and evolution as compared to other languages.  But Java 10 was quick to release after Java 9. With this release, the six-month release cycle has begun. You must think about why I am saying the six-month release cycle. I will explain it below in detail. To understand this concept, we have to understand LTS (Long Term Support model). In this post, we will read the most common and useful Java 10 Features and Java 10 tutorial.

Here is the table content of the article will we will cover this topic.
1. Local Variable Type Inference
2. Immutable Collections / Unmodifiable Collections
3. Optional.orElseThrow()
4. Garbage-Collector Interface
5. Application Class-Data Sharing
6. Experimental Java-Based JIT Compiler

LTS (Long Term Support model)

In 2017, Oracle decide to provide the Oracle Premier Support on LTS (Long Term Support model). Every LTS version will release after two years. After Java SE 8, Oracle has been designating releases as Long-Term-Support (LTS) releases. Java 8, Java 11, and Java 17 are LTS versions. Now the next planned LTS release is Java 21 in September 2023.

Non-LTS (Long Term Support model)

Non-LTS releases are continuous releases that are considered as 6 months release cycle. The Non-LTS release is considered a cumulative set of implementation enhancements of the most recent LTS release. Each Non-LTS release contains one or two major features that provide support for the LTS release.

In 2017, Oracle and Java community announced the 6 months release cycle. It means instead of waiting years for a major release, now Java versions will release by every 6 months. If a scheduled feature doesn’t complete in the 6-month cycle, then the feature which makes the cut gets boarded from release else it waits for the next scheduled cycle.

In this article, we’ll cover what’s new in java and what the Java 10 Features and Java 10 tutorial and changes introduced in JDK 10 are. There are two big changes from Java 10:

  1. The new var keyword
  2. the new six-month release cycle, that we have discussed above.

But there are many other interesting Java 10 Features and Java 10 tutorial and I tried to sort them. Let’s read them one by one.

Local Variable Type Inference

Local variable type inference was the biggest feature of Java 10. As we know we have to define a variable with its data type but from Java 10 onward we can use the var keyword to declare the local variables. We don’t need to specify the data type with the variable name. Now it’s the compiler’s responsibility to infer the type of the variable using the value provided. We will discuss it in a separate post with various types of examples and what will be restrictions and rules. You can read it here.

// Declaring and initlizing an int variable with value
int i = 5;

// Declaring and initlizing an String variable with value
String hello = "Hello world!";

// Creating an ArrayList
ArrayList<String> list = new ArrayList<String>();

// Creating a HashMap 
HashMap<Integer, String> hashMap = new HashMap<Integer, String>()

// Declaring and initlizing variable with value
var i = 5;

// Declaring and initlizing variable with value
var hello = "Hello world!";

// Creating an ArrayList
var list = new ArrayList<String>();

// Creating a HashMap 
HashMap<Integer, String> hashMap = new HashMap<Integer, String>()

Immutable Collections / Unmodifiable Collections

Immutable collection in java topics is an important part of Java 10. In Java 10, some new methods are introduced to get the immutable collection. In List, Set and Map interfaces, a new method copyOf() has been introduced. That can create new collection instances from existing ones.

Java 10 provides some more method in Collector class: toUnmodifiableList(), toUnmodifiableSet(), and toUnmodifiableMap() to get elements of a stream into an unmodifiable collection.

You can read the change from the below links.

1. List.copyOf(), Set.copyOf(), and Map.copyOf()

2. Collectors.toUnmodifiableList(), toUnmodifiableSet(), and toUnmodifiableMap()

import java.util.List;
import java.util.stream.Collectors;

public class NewMethodJava10
{
    public static void main(String[] args)
    {
        var integerIds = List.of(11, 22, 33, 44, 55);
        try
        {
            // Get an unmodifiable list by use of copyOf()
            List<Integer> copyOfIds = List.copyOf(integerIds);
            // Try to add element in unmodifiable list
            copyOfIds.add(66);
        }
        catch(UnsupportedOperationException e)
        {
            System.out.println("Collection can't modify.");
        }
        try
        {
            // Get an unmodifiable list by use Collector
            List<Integer> listOfEvenNumbers = integerIds.stream()
                    .filter(i -> i % 2 == 0)
                    .collect(Collectors.toUnmodifiableList());

            listOfEvenNumbers.add(66);
        }
        catch(UnsupportedOperationException e)
        {
            System.out.println("Collection can't modify.");
        }

    }
}

Output: Collection can’t modify.
Collection can’t modify.

Optional.orElseThrow()

Java 10 introduced a new method orElseThrow in the Optional class. It’s synonymous with and is now the preferred alternative to the existing get method. But before moving further let’s discuss the need for this method and why it was introduced?

In java 8, the Optional class was introduced to avoid NullPointerException. Java 9 also made some improvements in the Optional class. In java 9 some new methods were introduced. As we already know to get value from optional we use the get() method. Because Optional is a wrapper and we always call the isPresent() method whether a value exists or not.

Java 10 introduced a solution with the orElseThrow() method. This method is used to get the value from optional and it’s an exact copy of get() method only the name is different. But this method can throw an exception if value == null.

import java.util.Optional;

public class OptionalInJava10
{
    public static void main(String[] args)
    {
        String stringOne = "Hello world";
        var optionalStringOne =  Optional.ofNullable(stringOne);
        var valueStringOne  = optionalStringOne.orElseThrow();
        System.out.println(valueStringOne);

        String stringTwo = null;
        var optionalStringTwo =  Optional.ofNullable(stringTwo);
        var valueStringTwo  = optionalStringTwo.orElseThrow();
        System.out.println(valueStringTwo);
    }
}

Output: Hello world
Exception in thread “main” java.util.NoSuchElementException: No value present

Garbage-Collector Interface

The garbage collector is made up of various components in the JDK structure. Before Java 10, The implementation of these components was not accumulated. The code base of implementation was scattered.

In java 10, Oracle developers decided to refactor the implementation. Now, we have a clean interface within the JVM source code to allow alternative collectors to be quickly and easily integrated. It will improve the source-code isolation of different garbage collectors. Now it’s easy to exclude a GC from a JDK build and it is also easier to add a new GC without it affecting the codebase.

Application Class-Data Sharing

Application Class-Data Sharing is also known as Application CDS and Class data sharing is known as CDS.  The CDS was introduced to reduce footprint by sharing common class metadata across different Java processes. The Application Class-data sharing extends the CSD. Let’s discuss the reason behind this improvement.

Every java developer knows when JVM starts it performs some important steps, one of which is class loading in memory (You may be familiar with it, if not then read it from here). But many java developers are not familiar with Class-Data Sharing. So before moving to Application class-data sharing, I would like to tell you about class data sharing (CDS).

If there are multiple jars having several classes, then the lag in the first request is simply visible. There arises a problem with serverless architecture, where the boot time is critical. In order to carry forward the application startup time, Application class-data sharing is used that enables the bootstrap class loader to load classes that have been archived. It is to reduce footprint by sharing common class metadata across several Java processes.

Class-Data Sharing

Class-Data Sharing was introduced in JDK 5. When JVM starts, it loads multiple jars having serval classes (JDK class library) from the file system. Before java 9 it loaded from jre/lib/rt.jar file; since JDK 9 from the jmod files in the jmods directory.  JVM loads the class files that are extracted from the archives and converted into binary form. It reduces the start-up time and also reduce the dynamic memory footprint when multiple JVMs share the same archive file.

Why Class-Data Sharing has been used?

  1. Reducing the startup time of the JVM.
  2. Reducing the JVM’s memory footprint.

In Class-Data Sharing, when JVM starts it allows set classes to be pre-processed into a shared archive file that can then be memory-mapped at runtime to reduce startup time. It can also reduce dynamic memory footprint when multiple JVMs share the same archive file. It meant that multiple instances of the JVM can share class metadata, so it wouldn’t have to load them all the time.

How does Class-Data Sharing work?

  1. By use of command, it initially creates a file with the extension JSA (Java Shared Archive). The command is java -Xshare:dump, and it creates a file called classes.jsa. The .JSA file contains the complete class library in a binary format for the current architecture.
  2. When the JVM starts, the OS (Operating system) maps the .jsa file into the JVM’s memory. As this file is in binary format so it is faster than loading the jar or jmod files. The operating system loads the file into RAM, providing each JVM process with a read-only view of the same memory area.

Application class data sharing

Before Java 10, The CDS provides the functionality to bootstrap class loader to load archived classes. Since java 10, Application CDS allows the built-in system class loader, the built-in platform class loader, and custom class loaders to load archived classes. To take advantage of that, you just need to add the following parameter:

-XX:+UseAppCDS

Application Class-Data Sharing – Step by Step

It’s a bigger chance that it allows you to store your own application-specific classes in the Class-Data Sharing cache. Maybe it possibly decrease your startup times.

Suppose I am working on a small application, and I have two classes that I want to add to JSA file. So first of all, let’s create those files.

package com.JavaGoal.appcds;

public class Main
{
    public static void main(String[] args)
    {
        new Hello().printHello();
    }
}
package com.JavaGoal.appcds;

public class Hello
{
    // This method print message Hello world!
    public void printHello()
    {
        System.out.println("Hello world!");
    }
}

We will compile and package the classes as follows and then run the main class:

javac -d target/classes src/com/JavaGoal/appcds/*.java
jar cf target/helloworld.jar -C target/classes 
java -cp target/helloworld.jar com.JavaGoal.appcds.Main

We should now see the output: “Hello World!”.

If we want to use Application CDS, then we need to do a three-step process.

Step1: We will create a list of classes that should be archived by start-up the application. To do this we have run some commands that will create appropriate flags and indicate where you want to store the list.

To complete the first step, run the following command (on Windows, you must omit the backslashes and write everything on one line):

java -Xshare:off -XX:+UseAppCDS  -XX:DumpLoadedClassList=helloworld.lst  
-cp target/helloworld.jar com.JavaGoal.appcds.Main

NOTE: The above works only in OpenJDK. If you are using Oracle JDK, then you will get a warning.

Step 2: Now, we will create the JSA file from the class list.

     java -Xshare:dump -XX:+UseAppCDS \
    -XX:SharedClassListFile=helloworld.lst \
    -XX:SharedArchiveFile=helloworld.jsa \
    -cp target/helloworld.jar

Step 3: Let’s complete the last step and run the application, using that archive:

     java -Xshare:on -XX:+UseAppCDS \
    -XX:SharedArchiveFile=helloworld.jsa \
    -cp target/helloworld.jar com.JavaGoal.appcds.Main
Java 10 features

Experimental Java-Based JIT Compiler

JIT – Just in time is a compiler that is used to convert java byte code to machine code at runtime. This compiler was written in C++ and it’s difficult to modify.

In Java 9, the Graal Compiler was introduced which is an alternative to the JIT compiler (a Java compiler written in Java) and has been supplied as an experimental Ahead-of-Time (AOT) compiler. This compiler compiled the java program into a native executable file (e.g., an exe file on Windows). It provides support for the interpretation of the polyglot language.

Since java 10, It enables the possibility of using Graal also as a just-in-time (JIT) compiler.

 

Leave a Comment