Home » Java » Core Java » Chasing Java’s release train, from 8 to 16. Part 1: JDK 9, the last big banger

About Andrey Redko

Andrey Redko
Andriy is a well-grounded software developer with more then 12 years of practical experience using Java/EE, C#/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).

Chasing Java’s release train, from 8 to 16. Part 1: JDK 9, the last big banger

A lot has been said about JDK’s new 6 months release cadence cycle, and arguably, this is one of the most profound decisions being made in the recent history of the language and JVM platform in general. But if you, like me and other ~60% of the Java developers out there, stuck with JDK 8, the new releases mean little to your day to day job. But the language changes, the standard library changes, the JVM changes and so does the tooling around it. More importantly, the ecosystem also changes by aggressively raising the compatibility baselines. Java in 2021 is not the same as it was in 2020, 2017 and all the more in 2014, when Java 8 has seen the light. The soon to be out JDK 17, the next LTS release, would raise the bar even higher.

So the challenge many of us, seasoned Java developers, are facing is how to stay up to date? The risk of your skills becoming outdated is real. Hence this series of the blog posts: to consolidate the changes in the language, JVM, standard library and tooling over each release, primary from the perspective of the developer. At the end, we should be all set to meet the JDK 17 fully armed. To mention upfront, we are not going to talk about incubating or preview features, nor about come-and-go ones (looking at you, jaotc). Whenever it makes sense, the feature would have a corresponding JEP link, but overall there are many changes not covered by dedicated proposals. I will try to include as much as possible but there are chances some useful features may still slip away.

With that, let us open the stage with JDK 8.


Unsurprisingly, JDK 8 does not only receive the security patches and bugfixes but gets some of the new features from the upstream. The two notable ones are:

  • Improved Docker container detection and resource configuration usage: since 8u191, the JVM is fully container-aware (see please JDK-8146115). The support is only available on Linux based platforms and enabled by default.
  • JFR backport: since 8u262, JFR is supported seamlessly (see please JDK-8223147), no need to pass -XX:+UnlockCommercialFeatures and alike anymore

Although not strictly related, thanks to the JFR backport, the latest JDK Mission Control 8 release comes very handy to everyone. Hopefully, your organization does update to the recent JDK patch releases on the regular basis and these features are already available to you.


The JDK 9 release was just huge (90+ JEPs): not only from the perspective of the bundled features, but also from the impact on the platform and ecosystem. It was 2017 but even today the groundwork established by JDK 9 still continues. Let us take a look at the major features which went into it.

  • JEP-261: Module System: this change by itself is worth a book. Fast track to today, the debates are still ongoing if this feature is useful outside of JDK itself. The adoption of Java modules is not that high to be fair, and besides Automatic-Module-Name, not that many projects decided to take the full-fledged modularization path. Along with numerous JVM and standard library changes, the JPMS comes with:


    • New java command line options:
      • –add-exports: to export a package, which makes its public types and members accessible
      • –add-opens: to open a package, which makes all its types and members accessible
      • –patch-module: adds classes to a specific module
      • –add-modules: adds the listed modules and their transitive dependencies to the module graph
      • –add-reads: makes one module read another
      • –list-modules: lists the observable modules
      • –limit-modules: specifies the limit of the universe of observable modules
      • –describe-module: describes a specified module
      • –validate-modules: validates all modules
      • –illegal-access=permit|warn|debug|deny: accessing internal APIs
    • New javac command line options:
      • –add-modules: specifies root modules to resolve in addition to the initial modules
      • –limit-modules: specifies the limit of the universe of observable modules
      • –module: compiles only the specified module and checks time stamps
      • –module-path: specifies where to find application modules
      • –module-source-path: specifies where to find input source files for multiple modules
      • –module-version: specifies the version of modules that are being compiled
      • –add-exports: specifies a package to be considered as exported from its defining module
      • –add-reads: specifies additional modules to be considered as required by a given module
      • –release: compiles against the public, supported and documented API for a specific VM version
    • New jmod tool
  • JEP-260: Encapsulate Most Internal APIs: encapsulates most of the JDK’s internal APIs by default so that they are inaccessible at compile time, and prepare for a future release in which they will be inaccessible at run time. As we are going to see later on, the hardening efforts kicked off in this JEP are continued in later JDK releases.
  • JEP-282: jlink: The Java Linker: a tool that can assemble and optimize a set of modules and their dependencies into a custom run-time image. It is closely related to JEP-220: Modular Run-Time Images and essentially allows to bundle a highly optimized distribution tailored to the needs of your applications. As you may expect, jlink only works with applications which are fully modularized, otherwise you have to do heavy lifting yourself.
  • JEP 238: Multi-Release JAR Files: extends the JAR file format to allow multiple, Java-release-specific versions of class files to coexist in a single archive. The goal of this change is to allow third party libraries and frameworks to take advantage of the language or/and API features available in newer releases but still supporting the older ones. The feature has proven to be quite useful in practice but the tooling support around it, Apache Maven in particular, is still falling behind: see please here and here.
  • JEP-241: Remove the jhat Tool: jhat was an experimental, unsupported, and out-of-date tool, superior heap visualizers and analyzers have now been available for many years.
  • JEP-228: Add More Diagnostic Commands: defines additional diagnostic commands in order to improve the diagnosability of Hotspot VM and the JDK. In scope of this feature, new diagnostic commands have been added to jcmd tool:


    • VM.info
    • VM.class_hierarchy
    • VM.set_flag
    • JVMTI.data_dump
  • JEP-224: HTML5 Javadoc: enhances the javadoc tool to generate HTML5 markup. The primary drivers behind this feature are to increase the semantic value of web pages and to make it easier to create accessible web pages.
  • JEP-229: Create PKCS12 Keystores by Default: transitions the default keystore type from JKS to PKCS12. The applications may explicitly specify the keystore type they require.
  • JEP-244: TLS Application-Layer Protocol Negotiation Extension: extends the javax.net.ssl package to support the TLS Application Layer Protocol Negotiation (ALPN) Extension, which provides the means to negotiate an application protocol for a TLS connection. It is a necessary prerequisite for HTTP/2 support, both for client-side and for server-side.
  • JEP-226: UTF-8 Property Resource Bundles: changes the default file encoding for ResourceBundle class to load properties files from ISO-8859-1 to UTF-8, applications no longer need to convert the properties files using the escape mechanism.
  • JEP-243: Java-Level JVM Compiler Interface: introduces a Java based JVM compiler interface (JVMCI) enabling a compiler written in Java to be used by the JVM as a dynamic compiler. It paved the path for Graal JIT compiler integration into HotSpot VM.
  • JEP-222: jshell: The Java Shell (Read-Eval-Print Loop): a true gem of the JDK 9 release, an interactive tool to evaluate declarations, statements, and expressions of the Java programming language, together with an API so that other applications can leverage this functionality. Just use it, very handsome, luckily we have JShell Maven Plugin to take care of the classpath manipulations.
  • JEP-248: Make G1 the Default Garbage Collector: G1 becomes the default garbage collector on 32- and 64-bit server configurations. This change is based on the assumption that limiting latency is often more important than maximizing throughput.
  • JEP-271: Unified GC Logging: reimplements GC logging in a manner that is as consistent as is reasonable with the current GC logging format. There are a lot of details baked in, I would highly recommend the series of the articles (part 1, part 2) to learn about GC logging configuration and migration hints.
  • JEP-264: Platform Logging API and Service: defines a minimal logging API which platform classes can use to log messages, together with a service interface for consumers of those messages. A library or application can provide an implementation of this service in order to route platform log messages to the logging framework of its choice. If no implementation is provided then a default implementation based upon the java.util.logging API is used.


    This is quite valuable feature since the applications would be able to configure the JDK to use the same logging framework as the application itself. The Log4j2 already supports that but SLF4J is lagging a bit. In any case, the integration is looking quite straightforward.

  • JEP-277: Enhanced Deprecation: allows to communicate better the status and intended disposition of APIs in the specification. The @Deprecated annotation acquired two new properties: forRemoval and since.


    @Deprecated(since = "11", forRemoval = true)

    With such additions it became possible to express the expectations regarding the API lifecycle in more structural and formal way.

  • JEP-285: Spin-Wait Hints: defines an API to allow Java code to hint to the run-time system that a spin loop is being executed. It resulted into adding a new (empty) method to java.lang.Thread: onSpinWait().


    while ( /* condition */ ) {

    If you would like to learn more about how this method is being implemented in the HotSpot VM, please check JDK-8147844 issue.

  • JEP-287: SHA-3 Hash Algorithms: implements the SHA-3 cryptographic hash functions, quite timely addition to the Java’s security library. The MessageDigest implementation has been enhanced with SHA3-224, SHA3-256, SHA3-384 and SHA3-512 algorithms.
final MessageDigest digest = MessageDigest.getInstance("SHA3-512");

The JDK 9 changeset was massive, at the same time – this is the last big bang release. We have covered most interesting pieces of it, at least from the developer’s point of view. In the upcoming posts we are going to dissect other releases, one by one, and reveal the hidden gems of each.

Published on Java Code Geeks with permission by Andrey Redko, partner at our JCG program. See the original article here: Chasing Java’s release train, from 8 to 16. Part 1: JDK 9, the last big banger

Opinions expressed by Java Code Geeks contributors are their own.

(0 rating, 0 votes)
You need to be a registered member to rate this.
Start the discussion Views Tweet it!
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy
Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Inline Feedbacks
View all comments