×
Community Blog The Past and Present of JDK8 and JDK17 to the Future of JDK21

The Past and Present of JDK8 and JDK17 to the Future of JDK21

This article gives a retrospective review of JDK’s past while predicting JDK’s future.

By Tang Yueping (Lingli)

1

Background

Spring6 and SpringBoot3 launched in 2022. Before that, no matter how many new versions came out, most people were unwilling to upgrade and stuck to Java 8. This time, Spring came up with a big move. The lowest dependency of SpringBoot3 and Spring6 is JDK17! It skips JDK 8-16 and upgrades directly to JDK 17. So, why JDK 17?

Why JDK17?

There are so many new versions of JDK. Why did Spring choose JDK 17?

The main reason is that it is a commercially free LTS version announced by Oracle. LTS means Long Term Support, which is officially guaranteed to be supported for a long time.

2

The preceding figure shows the timeline of Oracle JDK support. As you can see, JDK 17 will be supported up to September 2029. According to the speed of technology update iteration, free commercial use for eight years is a good intention, so users can safely upgrade JDK to JDK 17. (Also, JDK 8 will be supported for a longer period that can be extended to December 2030.)

Since the creation of JDK, JDK 7, JDK 8, JDK 11, and JDK 1 have been supported long-term. JDK 17 will be the most important LTS version since Java8. It is the result of eight years of efforts by the Java community.

Java8 has been the pain point in the Java community. Java8 provides many features, such as Lambda expression and Optional class. Also, Java8 has a long support time. These are the reasons why it can be used as yet. It represents a tug-of-war between stability-oriented corporate management and developers that embrace changes. No upgrades! It becomes the tacit choice of major companies. Now, that balance may be broken. Java's dominant framework, SpringBoot chooses the smallest supported Java LTS version, which is the latest Java17.

So, let's see, from JDK8 to JDK17, what are the results of the Java community's eight years of hard work?

New Features from JDK8 to JDK17

New Features of JDK9 (September 2017)

  • Modular
  • Factory methods are provided, such as List.of(), Set.of(), Map.of(), and Map.ofEntries().
  • Interfaces support private methods.
  • Optional Class Improvements
  • JAR Packages Compatible with Multiple Versions
  • JShell Tool
  • Improvement of Try-with-resources
  • Improvements to the Stream API
  • Set G1 as the JVM default garbage collector
  • APIs that support HTTP2.0 and WebSocket

Its important features are mainly API optimization (such as Client API supporting HTTP2) and JVM using G1 as the default garbage collector.

New Features of JDK10 (March 2018)

  • Local variable type inference, similar to JS, can use var to modify local variables. After compilation, the true type of the value is inferred.
  • Improvements to Immutable Collections
  • Parallel Full Garbage Collector G1 to Optimize G1 Latency
  • Thread local handshake allows thread callbacks to be executed without executing a global VM safe point. A single thread can be stopped.
  • New orElseThrow() method in Optional
  • Class Data Sharing
  • Unicode Language Label Extension
  • Root Certificates

Its important features are local variable type inference is realized through the var keyword, making Java language a weak type language and G1 garbage collection of JVM changing from single thread to multi-thread parallel processing, thus reducing G1 pause time.

New Features of JDK11 (September 2018) (LTS Version)

  • Add some string processing methods
  • Local Variable Syntax for Lambda Parameters
  • HTTP Client Rewrite supports HTTP/1.1, HTTP/2, and WebSockets.
  • Run a single Java source code file, such as java Test.java
  • ZGC: Scalable and low-latency garbage collector. ZGC can be seen as a more fine-grained memory management strategy than G1. Since the continuous allocation and recycling of the memory will generate a large amount of memory fragmentation space, a defragmentation policy is required. The thread for memory reference needs to be logically suspended during defragmentation. This process is called Stop the world. The thread logic can only continue to run when the process is complete. (Parallel Reclaim)
  • Support for TLS 1.3 Protocol
  • Flight Recorder, a Data Collection Framework for OS, JVM, and a JDK-based Event
  • Enhancements to the Stream, Optional, and Collection APIs

Its important features are improvements for JDK9 and JDK10, mainly for stream, collection, and other APIs and a new ZGC garbage collector.

New Features of JDK12 (March 2019)

  • Switch expression extension with a return value
  • Add NumberFormat to format complex numbers
  • Character strings support the transform and indent operations
  • Add Method Files.mismatch (Path, Path)
  • Teeing Collector
  • Support for Unicode 11
  • Shenandoah GC, New GC Algorithm
  • The optimization of the G1 collector divides the garbage of the GC into a mandatory and an optional part. The mandatory part will be recycled, while the optional part may not be recycled, improving the efficiency of the GC.

Its important features are the switch expression syntax extension, G1 collector optimization, and new Shenandoah GC garbage collection algorithm.

New Features of JDK13 (September 2019)

  • The switch expression is extended. The switch expression adds the yield keyword to return the result. The function is similar to return. If no result is returned, break is used.
  • Text blocks are upgraded to """. It introduced text blocks. You can use three double quotation marks (""") to indicate text blocks. You do not need to use line break escape characters inside text blocks.
  • SocketAPI refactoring, the underlying implementation of Socket is optimized, and NIO is introduced.
  • FileSystems.newFileSystem New Method
  • ZGC is optimized to enhance ZGC to release unused memory and return the in-heap memory space marked as idle for a long time to the operating system. It aims to ensure that the heap size is not less than the configured minimum heap memory size. If the maximum heap size is the same as the minimum heap memory size, the memory will not be released to the operating system.

Its important features are ZGC optimization, releasing memory back to the operating system, and introducing NIO to the underlying socket implementation.

New Features of JDK14 (March 2020)

  • Instanceof pattern matching and instanceof type matching syntax simplification can directly assign values to objects, such as if(obj instanceof String str). If obj is a string type, directly assign values to str variables.
  • Introduce the record type, which is similar to the @Data annotation of Lombok. It can automatically generate constructors, equals, getters, and other methods like Lombok.
  • Switch Expression-Standardization
  • Improve the NullPointerExceptions prompt information, print the null pointer exception thrown by the specific method, avoid the trouble that it is impossible to judge which function throws the exception when multiple functions in the same line of code are called, and facilitate exception troubleshooting
  • Delete a CMS garbage collector

New Features of JDK15 (September 2020)

  • EdDSA Digital Signature Algorithm
  • Sealed Classes (Preview): The sealed keyword is used to modify abstract classes to only restrict specified subclasses to implement or inherit abstract classes to avoid abuse of abstract classes.
  • Hidden Classes
  • Remove the Nashorn JavaScript engine
  • Improve java.net.DatagramSocket and java.net.MulticastSocket underlying implementation.

New Features of JDK16 (March 2021)

  • Allows use of C ++ 14 features in the JDK C ++ source code
  • ZGC performance optimization removes the ZGC thread stack processing from the safe point to the concurrent phase.
  • Add Unix Domain Socket Channel
  • Elastic Meta-space Capability
  • Provide the jpackage tool for packaging standalone Java applications

JDK16 is equivalent to the formal introduction of some features of JDK14 and JDK15, such as instanceof pattern matching, record introduction, etc. JDK16 became the final version.

New Features of JDK17 (September 2021) (LTS version)

  • Free Java License
  • JDK 17 will replace JDK 11 as the next long-term support release.
  • Spring 6 and Spring Boot 3 require JDK17.
  • Remove experimental AOT and JIT compilers
  • Restore always-strict floating-point definitions
  • The sealed class is formally introduced to restrict the implementation of abstract classes.
  • Unify log asynchronous refresh. Logs are written to the cache and then asynchronously refreshed.

Although JDK17 is an LTS version, it does not introduce prominent features (like JDK8 and JDK11), mainly integrating and improving the previous versions.

Detailed Explanation of Important Characteristics

Java Modularity

Java Platform Module System (JPMS) is the highlight of the Java 9 release. It is known as the Jigshaw Project. Modules are new structures, just like the packages we already have. An application developed with the new modular programming can be viewed as a collection of interacting modules with well-defined boundaries and dependencies between them.

JPMS supports writing modular applications and modularizing JDK source code. JDK 9 comes with about 92 modules (which can be changed in the GA version). The Java 9 Module System has a java.base module. It is called the basic module. It is an independent module and does not depend on any other modules. All other modules rely on java.base by default.

In Java modular programming:

  • A module is usually a jar file with a file module-info.class under the root directory
  • To use the module, include the jar file in the modulepath instead of the classpath. The modular jar file added to the classpath is a normal jar file, and the module-info.class file will be ignored.

A typical module-info.java class is shown below:

module helloworld {     
    exports com.alibaba.eight; 
} 
module test {     
    requires helloworld; 
}

Summary: The purpose of modularization is to enable JDK components to be split, reused, replaced, and rewritten. For example, if you are unsatisfied with Java’s GUI, you can implement a GUI yourself. If you are unsatisfied with Java syntax, you can replace javac with other languages and compilers for other languages, such as kotlin and kotlinc. Without modularization, it is almost difficult to implement. Each time you modify a module, it is unfeasible for you to recompile the entire JDK and release the entire SDK. Modularization can help realize effective customization and deployment.

Local Variable Type Inference

In versions prior to Java 10, when we wanted to define local variables, we need to provide an explicit type on the left side of the assignment and an implementation type on the right side of the assignment.

MyObject value = new MyObject();

In Java 10, local variable type inference is provided, and variables can be declared by var.

var value = new MyObject();

Local variable type inference will introduce the var keyword without explicitly specifying the type of the variable.

The local variable type inference is the syntactic sugar that Java 10 provides to developers.

Although we use var to define in the code, the virtual machine does not know this var. In the process of compiling java files into class files, the real type of variables will be used to replace var.

HTTP Client API - HttpClient for Responsive Streaming

Java has been using HttpURLConnection for HTTP communication for a long time. Over time, the requirements became complex, and the requirements of the application became demanding. Prior to Java 11, developers had to resort to feature-rich libraries, such as Apache HttpComponents or OkHttp.

We see that the Java 9 release includes a HttpClient implementation as an experimental feature. It has evolved to the final feature of Java 11. Now, Java applications can communicate over HTTP without any external dependencies.

As a new HTTP connector officially launched in JDK11, the supported functions are new. The main features are listed below:

  • Full Support for HTTP 2.0 or HTTP 1.1
  • Support for HTTPS and TLS
  • Simple blocking usage methods
  • Support asynchronous sending and asynchronous time notifications
  • Support for WebSocket
  • Support for Responsive Streaming

HTTP2.0 is also supported by other clients, while HttpClient uses CompletableFuture as asynchronous return data. WebSocket support is an advantage of HttpClient. The support of responsive streams is a major advantage of HttpClient.

The NIO model, functional programming, CompletableFuture asynchronous callbacks, and responsive streams in HttpClient equip HttpClient with strong concurrent processing capabilities, so its performance is high and its memory footprint is less.

Syntactic Sugar

Stream API Improvements

Collectors.teeing()

The teeling collector has been exposed as a static method Collectors::teeing. The collector forwards its input to the other two collectors and combines their results with the function.

Example:

List<Student> list = Arrays.asList(
        new Student("A", 55),
        new Student("B", 60),
        new Student("C", 90));
// Average Score and Total Score
String result = list.stream().collect(Collectors.teeing(
        Collectors.averagingInt(Student::getScore),
        Collectors.summingInt(Student::getScore),
        (s1, s2) -> s1 + ":" + s2));
// The Lowest Score and the Highest Score
String result2 = list.stream().collect(Collectors.teeing(
        Collectors.minBy(Comparator.comparing(Student::getScore)),
        Collectors.maxBy(Comparator.comparing(Student::getScore)),
        (s1, s2) -> s1.orElseThrow() + ":" + s2.orElseThrow()
));
System.out.println(result);
System.out.println(result2);
Add Stream.toList Method (JDK16)
List<String> list = Arrays.asList("1", "2", "3");
// Wrote this before.
List<Integer> oneList = list.stream()
    .map(Integer::parseInt)
    .collect(Collectors.toList());
// Now write like this.
List<Integer> twoList = list.stream()
    .map(Integer::parseInt)
    .toList();

Switch Expression Improvements

Support for Arrow Expressions (JDK12 Preview JDK14 Standard)

This change extends the switch statement so it can be used as a statement or expression. Instead of defining a statement to break each case block, we can simply use the arrow syntax:

boolean isWeekend = switch (day) {
  case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> false; 
  case SATURDAY, SUNDAY -> true;
  default -> throw new IllegalStateException("Illegal day entry :: " + day);
};
int size = 3;
String cn = switch (size) {
    case 1 -> "One";
    case 2 -> "Two";
    case 3, 4 -> "Three";
    default -> "Unknown";
};
System.out.println(cn);
// To use this preview feature, we must explicitly instruct the JVM with the-enable-preview flag during application startup. 
yield Keyword (JDK13)

With yield, we can efficiently return values from switch expressions and implement the strategy pattern easily.

public class SwitchTest {
    public static void main(String[] args) {
        var me = 4;
        var operation = "Square";
        var result = switch (operation) {
            case "Double" -> {
                yield me * 2;
            }
            case "Square" -> {
                yield me * me;
            }
            default -> me;
        };
        System.out.println(result);
    }
}

String

Text Block Improvements (jdk13)

Earlier, to embed JSON in our code, we declared it as a string literal.

String json  = "{\r\n" + "\"name\" : \"lingli\",\r\n" + "\"website\" : \"https://www.alibaba.com/\"\r\n" + "}";

Now, let's write the same JSON.

String json = """ 
{     
    "name" : "Baeldung",     
    "website" : "https://www.alibaba.com/" 
} 
""";

There is no need to escape double quotes or add carriage returns. After using text blocks, it is easier to write, read, and maintain embedded JSON.

More APIs
  • isBlank(): Return true if the string is empty or if the string only contains spaces (including tabs). Note: isEmpty() only returns true if the length is 0.
  • lines(): Split a string into a stream of strings, each containing one line.
  • strip(): From the beginning and end
  • StripLeading()/stripTrailing() only removes spaces at the beginning and the end.
  • repeat(int times): Return a string that takes the original string and repeats the string a specified number of times.
  • readString(): It allows you to read strings directly from file paths.
  • writeString(Path path): Write a string to a file at a specified path
  • indent(int level): The Specified Amount of Indentation in the String Negative values only affect the leading whitespace.
  • transform(Function f): Apply the given lambda to a string

Pattern Matching of instanceof (JDK14 Preview, JDK16 Final Confirmation)

Before:

Object obj = "Dayang";
if (obj instanceof String) {
    String t = (String) obj;
    // TODO
}

Now:

Object obj = "Dayang";
if (obj instanceof String t) {
    // TODO At this time, t is already of the String type.
}

Record Class (JDK16 Formal)

Traditional Java applications create a class, instantiate the class through this creating method, and access or set the value of a member variable through getter and setter methods. With the record keyword, your code becomes more concise.

/**
 * record class
 * You can overwrite equals() hashCode() toString() method without writing get and set.
 * @author DAYANG
 */
record User(String name, Integer age) {
    
    @Override
    public String toString() {
        return "User[" +
                "name='" + name + '\'' +
                ", age=" + age +
                ']';
    }
    @Override
    public boolean equals(Object obj) {
        return false;
    }
    @Override
    public int hashCode() {
        return 0;
    }
}

JVM

GC Changes

JDK9: Set G1 as JVM default garbage collector.

JDK10: Parallel full garbage collector G1, which improves the latency of G1 through parallel Full GC. The implementation of full GC for G1 uses the single-thread-purge-compression algorithm. JDK 10 began using the parallelize-purge-compression algorithm.

JDK11: A new generation of ZGC garbage collectors (experimental) is launched. The goal is that GC pause time will not exceed 10ms, which can handle both hundreds of megabytes and several terabytes.

JDK14: Remove the CMS garbage collector, deprecate the garbage collection algorithm combination of ParallelScavenge + SerialOld GC, and port the ZGC garbage collector to the macOS and Windows platforms.

JDK 15: ZGC (JEP 377) and Shenandoah (JEP 379) are no longer experimental features. The default GC is still G1.

JDK16: Enhance ZGC. ZGC gets 46 enhancements and 25 bug fixes with no more than 10ms of controlling stw time.

Metric Test

Throughput Comparison

3

In terms of throughput, there is not much difference between JDK 8 and JDK 11 in Parallel, and JDK 17 is about 15% higher than JDK 8. JDK 17 in G1 is 18% higher than JDK 8. ZGC was introduced in JDK 11, and JDK 17 improved by more than 20% compared with JDK 11.

Latency Comparison

4

In terms of GC latency, the improvement in JDK 17 is pronounced. We can see that efforts to reduce GC pauses have paid off, and many of the improvements are due to GC improvements.

In Parallel, JDK 17 improves by 40% compared with JDK 8 and JDK 11. In G1, JDK 11 improves by 26% compared with JDK 8, and JDK 17 improves by nearly 60% compared with JDK 8. Compared with JDK 11, JDK 17 in ZGC improves by more than 40%.

Comparison of Pause Time

5

We can see that the ZGC in JDK 17 is well below the target: sub-millisecond pause time. The G1's goal is to maintain a balance between latency and throughput, far below its default target: 200 milliseconds of pause time. ZGC is designed to ensure that the pause time does not change with the size of the heap, and we can see what happens when the heap is expanded to 128GB. From a pause time perspective, G1 is better at handling larger heaps than Parallel since it can guarantee that the pause time meets a specific goal.

Resource Usage

6

The figure above compares the peak native memory usage of three different collectors. Since both Parallel and ZGC are stable from this perspective, we should take a look at the raw numbers. We can see that G1 has improved in this area, mainly because all functions and enhancements have improved the efficiency of memory set management.

Summary: No matter which collector is used, the overall performance of the JDK 17 has been improved compared to the old version. In JDK 8, Parallel was the default setting, but it was changed to G1 in JDK 9. Since then, the G1 has improved faster than Parallel, but in some cases, Parallel may still be the best choice. The addition of ZGC (officially used by JDK 15) has become a third high-performance alternative.

Other

Sealed Classes and Interfaces (15 Preview 17 Formal)

Prior to Java 15, all classes that could inherit from other classes without restriction could implement a public interface unless the inherited class was declared final.

Now in Java 15, a class or interface can be declared as a sealed class or interface with the sealed modifier to restrict its inheriting classes.

/**
 * Define an abstract sealed class Pet. Its implementation classes can only be Dog or Cat. Other implementation classes are not allowed.
 */
public abstract sealed class Pet
    permits Dog, Cat {}
final class Dog extends Pet {
}
final class Cat extends Pet {
    
}
// Sealed classes and interfaces restrict other classes or interfaces from extending or implementing them.
public sealed interface Shape{
    final class Planet implements Shape {}
    final class Star   implements Shape {}
    final class Comet  implements Shape {}
}
public abstract sealed class Test{
    final class A extends Test {}
    final class B extends Test {}
    final class C extends Test {}
}

EdDSA Algorithm

Edwards-Curve Digital Signature Algorithm (EdDSA) is another additional digital signature scheme added in Java 15 with JEP 339. It provides better performance and secure signatures compared to other available signature schemes.

Summary and Outlook

Summary

  1. Spring takes the lead and rushes directly to JDK17. If Spring6 still supports Java8, many technical frameworks should be compatible with Java8. Therefore, Spring should take the lead and develop Java17 together. However, some frameworks do not support JDK17 yet.
  2. Performance Upgrade: After changing from Java8 to Java11 alone, the performance improved by 10% (rewriting the NIO bottom layer), not to mention the JVM-related optimization to the JDK17 process. However, performance optimization alone is not enough to attract enterprises to upgrade JDK. After all, performance optimization can be achieved by adding machines. Don't bother upgrading; not to mention there may be a security risk.
  3. JDK21 could become a true classic. Currently, there is no Project loom function, which means there is no coroutine, and the performance is far worse. For example, Alibaba's open-source JDK8 and JDK11 have a non-intrusive coroutine.

Judging from the development trend, the project loom function has been previewed in JDK19. It can be found that many Java tools in this version have begun to upgrade for loom. Project loom will be officially launched in JDK21, which is a long-term supported version. Please look forward to it.

Various servlet containers, as well as jetty, netty, vert.x, etc., found the corresponding upgrade label in their latest version of the release note, saying they have added certain support. The most important is loom (or virtual thread support). We predict that once JDK21 is released, more software will be developed!

Outlook

The upgrade of JDK is an inevitable trend.

Some people may think the upgrade will cause extra work. Considering security risks, they are less likely to upgrade. There are no substantial benefits but risks. However, considering Oracle will no longer maintain JDK8 and Spring will no longer maintain past versions in the future, to keep up with the times and use the latest technology, this will promote the upgrade of JDK.

When more companies use JDK17, more new frameworks in the future will support JDK17 (at minimum) because it is not worth it to only be compatible with the old JDK. When most frameworks, communities, and forums are discussing JDK17 technologies and various problem-solving methods, enterprises will inevitably be pushed to upgrade.

References

https://zhuanlan.zhihu.com/p/480293185

https://blog.oxings.com/article/31.html

https://blog.csdn.net/best_luxi/article/details/122543074

0 1 0
Share on

Alibaba Cloud Community

1,053 posts | 259 followers

You may also like

Comments