Why Migrate to Java 11/12 from Java 8?

Mritunjai Kumar Rai
TestVagrant
Published in
7 min readJan 3, 2020

As the Java is moving forward and updating quickly, so, at an interval of every six months release cycle, the new licensing and long-term support models to cope with the rate of new technology innovation.

Why upgrade from JDK 8 to JDK 11?

  • Next LTS version (if you own a commercial license).
  • Oracle no longer offers JRE and Server JRE downloads; consequently, Auto-Update is not available anymore.
  • Oracle no longer provides a 32-bit Windows download.
  • Java Applet, Java Web Start, Java Plugin, and Java Control Panel are not available in JDK. See Removal of the Deployment Stack.
  • JavaFX is no longer included in the JDK. It is now available as a separate download from https://openjfx.io/.
  • JAXB and JAX-WS are no longer bundled with JDK. See Removal of Java EE and CORBA Modules.
  • Support parallel full garbage collection on G1.
  • Free Application Class-Data Sharing feature.
  • Free low overhead Flight Recorder and Heap Profiler.
  • Heap allocation on alternative memory devices.
  • New ZGC and Epsilon garbage collectors.
  • Transport Layer Security (TLS) 1.3.
  • JShell.
  • Support for “shebang” Java files! #!/bin/java
  • Deprecations & removals of Library
  • API updates

Long term Support: Open JDK & Oracle JDK Both have the same features. Open JDK is an open-source and Oracle JDK java proprietary license. Till Java 10, can use Open JDK & Oracle JDK in production free of charge but from Java 11, we can only use Open JDK as free but not Oracle JDK in production. Few important points about LTS.

  • Every year, 2 releases from Java until 2028(Java 31).
  • Long Term Support Release for every 3 years. So after Java 8, next LTS is Java 11.
  • 3-year support commitment is minimum. and LTS is only applying for Oracle JDK. We can buy support for Java 11 for more than 3 years also.
  • All Open JDK have only 6-month support until then next major release. So either you buy LTS support or switch every six-month releases.

Major new features in Java 11/12

Launching Single-file Source-Code: If I say write a java program we follow the below steps.

public class HelloUniverse{
public static void main(String[] args) {
System.out.println("Hello Universe");
}
}
Before Java 11:
Compile
:$javac HelloUniverse.java
Run:$java HelloUniverse
O/p:Hello Universe
In Java 11:
Run:$java HelloUniverse.java
O/p:Hello Universe

Now using a single source, the compiler will directly execute .java to output, no .class file will be generated.

Note: This feature is only limited to a single source file.

Scripting Using java: Using shebang(“#!”), we can develop executable javascript and run from the command line.

./listallfiles#!/usr/bin/java --source 11import java.nio.file.*;public class ListFiles {
public static void main (String ... args) throws Exception
{
Files.walk(Path.get(args[0]))
.forEaach(System.out::println);
}
}
How to Run:
$chmod +x listallfiles
$./listallfiles . // Here "." is a current directory.

Deprecations & Removals

  • Removing a Java EE and CORBA modules from JDK.
  • Removed Thread.destroy() and Thread.stop() methods .
  • Removed Applets and Java Web Start.

Language & Library Improvements

  • HttpClient API: The HTTP Client was replaced with java.net.HttpURLConnection in Java 11. It can be used to request HTTP resources over the network. It supports HTTP/1.1 and HTTP/2, both synchronous and asynchronous programming models, handles request and response bodies as reactive-streams, and follows the familiar builder pattern.

Example: GET request that prints the response body as a String

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://openjdk.java.net/"))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
  • Library Improvements: Added a few methods in String library like “repeat”, isBlank(), strip, lines.
  • Local Variable syntax for Lambda expression: Use var in lambdas

Before Java 11: We were using explicit type in a lambda expression.

// Any local variable declaration
List<String> list = new ArrayList<String>();
Stream<String> stream = getStream()
// For Lambda Expression.
(String a, String b) -> a.concat(b)

Java 11: Can use var in lambda expression without using an explicit type.

// Any local variable declaration.
var list = new ArrayList<String>();
var stream = getStream();
// For Lambda Expression.
(var a, var b) -> a.concat(b)
  • Nest based access control: nests allow nested classes to be compiled to different class files that belong to the same enclosing class. These are then allowed to access each other’s private classes without the use of synthetic/bridge methods.

Performance & Security Improvements

  • Garbage Collector Improvements: Java manages heap memory for you. You run your application inside a virtual machine (JVM). The JVM does the work of allocating space when necessary and freeing it when it is no longer needed. The garbage collector (GC) is what does this work for you. Recycling memory involves garbage collection “cycles” that have an impact on performance.
  • G1 GC is a default Garbage collector since Java 9. After incremental improvement GC in Java 11 is 60% better than earlier.
  • Java 11 introduced Epsilon and the Z garbage collector (ZGC) and we can pick up better-suited GC for our application.
  • Security improvements: TLS 1.3: Now TLS 1.3 implemented in JDK. Older legacy algorithms pruned and all handshake algorithm except the message is encrypted.

Java 12 Changes

JDK 12 provides a small number of new features and APIs, with the switch expression being the most interesting to developers. Users of G1 will no doubt appreciate the performance improvements.

API updates

1. Collectors.teeing() in Stream API: A teeing collector has been exposed as a static method Collectors:: teeing. This collector forwards its input to two other collectors before merging their results with a function.

teeing(Collector, Collector, BiFunction) accepts two collectors and a function to merge their results. Every element passed to the resulting collector is processed by both downstream collectors, then their results are merged using the specified merge function into the final result.

For example, in a given list of employees, if we want to find out the employee with a maximum salary and minimum salary, we can do it in a single statement using the teeing collector.

public static void main(String[] args) {
List<Employee> employeeList = Arrays.asList(
new Employee(1, "A", 100),
new Employee(2, "B", 200),
new Employee(3, "C", 300),
new Employee(4, "D", 400));

HashMap<String, Employee> result = employeeList.stream().collect(
Collectors.teeing(
Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
Collectors.minBy(Comparator.comparing(Employee::getSalary)),
(e1, e2) -> {
HashMap<String, Employee> map = new HashMap();
map.put("MAX", e1.get());
map.put("MIN", e2.get());
return map;
}
));

System.out.println(result);
}
  • String API Changes:Added String.indent() . , String.transform() and Files.mismatch(Path, Path)
  • Switch Expression: Java 12 has enhanced Switch expressions for Pattern matching. Instead of having to define a break statement per case block, we can simply use the arrow syntax.

Old Switch Expression:

public String getTextViaBreak(int number) {
String result = switch (number) {
case 1:
case 2:
break "one or two";
case 3:
break "three";
case 4:
case 5:
case 6:
break "four or five or six";
default:
break "unknown";
};
return result;
}

New Switch Expression:

public String getTextViaArrow(int number) {
String result = switch (number) {
case 1, 2 -> "one or two";
case 3 -> "three";
case 4, 5, 6 -> "four or five or six";
default -> "unknown";
};
return result;
}
Note: Its preview feature and not going to run in your ide directly.
Follow below steps to run.
$javac --enable-preview --release 13 SwitchExpression.java
$ java --ennable-preview SwitchExpression
  • JVM Changes

1. A Low-Pause-Time Garbage Collector (Experimental)

RedHat iniRedHat initiated Shenandoah Garbage Collector to reduce GC pause times. The idea is to run GC concurrently with the running Java threads.

2. Promptly Return Unused Committed Memory from G1: Starting Java 12, G1 will now check Java Heap memory during the inactivity of application and return it to the operating system. This is a preemptive measure to conserve and use free memory.

3. Java Microbenchmark: Stands for Java Microbenchmark Harness. Writing benchmark measures the performance of a small part of larger applications.

import org.openjdk.jmh.annotations.Benchmark;public class MyBenchmark {
@Benchmark
public void testMethod() {
// This is a demo/sample template for building your JMH benchmarks. Edit as needed.
// Put your benchmark code here.
int a = 1;
int b = 2;
int sum = a + b;
}
}

4. Default CDS Archives: This enhances the JDK build process to generate a class data-sharing (CDS) archive, using the default class list, on 64-bit platforms. The goal is to improve startup time. From Java 12, CDS is by default ON.

Conclusion: Lots of things have changed since Java 8: we get releases every 6 months; licensing, updates and support have changed; where we get our JDK from may have changed. On top of that, of course, there are new language features, including the major changes that went into Java 9. But now that Java 11 has replaced Java 8 as the latest LTS, and now that major libraries, frameworks, and build tools have adopted the latest versions of Java, it is a good time to migrate your application to Java 11 or 12.

You can find the sample GitHub code here.

Happy Learning!

--

--