Posts

Java 18 一 many new features in a non-LTS release

Jan 27, 2022
Dmitry Chuyko
15.1

Contents

  1. Overview
  2. New features
    1. JEP 400: UTF-8 by Default
    2. JEP 408: Simple Web Server
    3. JEP 413: Code Snippets in Java API Documentation
    4. JEP 416: Reimplement Core Reflection with Method Handles
    5. JEP 417: Vector API (Third Incubator)
    6. JEP 418: Internet-Address Resolution SPI
    7. JEP 419: Foreign Function & Memory API (Second Incubator)
    8. JEP 420: Pattern Matching for switch (Second Preview)
    9. JEP 421: Deprecate Finalization for Removal
  3. Conclusion

Overview

Java 18 is released and available for everyone! Our instance of Java 18, Liberica JDK 18, is ready for download. It is not an LTS release, so the changes and enhancements are not as huge as in last year’s Java 17, and yet, there are some interesting new features! In the previous release, there were a lot of functionalities deprecated for removal or removed, but this year, there are not only upgrades to the existing JEPs, but some completely new enhancements. What is interesting is that some of those enhancements were functioning at the time when Java 17 came out, but they required additional testing, so in case you upgrade to Java 18, you will see them enhanced and stabilized. This is another example of how Java™ is being constantly tested and upgraded with every release by many participants of this open source project, including BellSoft.

If you have any questions, our engineers are glad to provide you with all the information you need to decide if you are ready to upgrade.

So without further ado, let us explore the new features of Java 18!

New features

JEP 400: UTF-8 by Default

A lot of APIs (including the standard Java APIs) use default charset in the applications, but what exactly is a default charset? Before it was environment-dependent, meaning that it could be different, as an example, for Windows, Linux, and Mac users. So the same application (even launched on the machine) by different users could corrupt text written in some languages (especially logographic ones).

To fix this issue, a decision was made to use the most wide-spread charset, the UTF-8.

The potential problem is that new issues may arise after migrating to Java 18 from earlier versions. If the source files were encoded with UTF-16, the javac compiler is affected because it assumes that .java source files are encoded with the default charset unless configured otherwise. So this should be noted when migrating from earlier versions of Java™.

But as you can still set other charsets as default manually, no huge problems are expected with this change, and it will ensure more stable work in the future.

JEP 408: Simple Web Server

This JEP adds the command to run the web server with minimal functionality, loopback address, and port 8000 intended for testing and learning. The files are served from the current directory. The command itself is

$ jwebserver

In case of the successful startup, jwebserver prints a message to System.out with the list of local addresses and the absolute path of the directory being served.

The server is customizable and enhanced with new APIs for server creation and customized request handling. The new classes are built on the existing classes and interfaces in the com.sun.net.httpserver package.

The goal of this out-of-the-box solution is to provide means for easy testing, prototyping, and training.

JEP 413: Code Snippets in Java API Documentation

This change could be perceived as small, but for some developers it is the most important and exciting one of the whole release! It introduces an @snippet tag for JavaDoc’s Standard Doclet, that simplifies the inclusion of example source code in API documentation.

It not only marks up the code included in the comments, but also validates it the same way as it does the main code, drastically reducing the chance of human error. This enhancement is full of features like compatibility with both internal and external snippets , text highlighting, and linking the text to the declarations elsewhere in the API.

All in all, this feature will make the developer’s life much easier when they have to dig into other people’s code.

JEP 416: Reimplement Core Reflection with Method Handles

java.lang.reflect API is now reimplemented using the method handles, replacing the bytecode-generating implementations of Method::invoke, Constructor::newInstance, Field::get, and Field::set. The older VM’s native reflection mechanism is used only during early VM startup, before the method-handle mechanism is initialized.

This enhancement will lessen the usage of unsafe APIs in Core Reflection to the minimum and also allow the better utilization of new Java™ features such as those introduced in Project Valhalla.

JEP 417: Vector API (Third Incubator)

The Vector API introduced in Java 16 can in some cases (like financial operations, machine learning, and cryptography) greatly boost the performance. It helps writing complex vector algorithms in Java™ in case, when using the existing HotSpot auto-vectorizer is not enough to achieve the complex computation, and you need to utilize the user model of vectorization.

The third incubation is built in accordance with community feedback and adds some new functionality, with two most notable enhancements: support for the ARM Scalar Vector Extension (SVE) platform, and improved performance of vector operations that accept masks on architectures that support masking in hardware.

We already provided an example of how Vector API impacts the performance at the time of the second incubation, and proved it to be a working solution.

JEP 418: Internet-Address Resolution SPI

To resolve the host names to internet protocol (IP), Java™ uses the java.net.InetAddress API, which in turn utilizes the OS’s resolver. Usually it works with the combination of local hosts file and the DNS (Domain Name System).

This JEP introduces the service-provider interface so the java.net.InetAddress API could use alternative resolvers.

This is done with several goals in mind, including the testing purposes and customization capabilities. And last but not the least, an alternative resolver could implement the DNS client protocol directly, without it being blocked on the OS-level, which allows, for example, the unrestricted utilization of Project Loom, that can now use multiple virtual threads to process the network requests.

The new methods for the InetAddress API allow to manually include the implementation that will work without locking and use a service loader to locate a resolver provider.

JEP 419: Foreign Function & Memory API (Second Incubator)

This is another upgrade of the feature introduced in an earlier release to replace the Java Native Interface (JNI) with a superior, pure Java™ development model. It allows the usage of native libraries, foreign functions, and accessing the foreign memory with boosted performance.

In the second incubator stage, the new carriers are implemented (boolean, MemoryAddress), with a simpler API to obtain downcall method handles and manage temporal dependencies between resource scopes. A new API for copying Java arrays to and from memory segments is introduced.

JEP 420: Pattern Matching for switch (Second Preview)

And yet another update of the previously implemented feature. It allows an expression or statement to be tested against several patterns, each with a specific action. Delivered before as the preview feature, it now provides two new enhancements.

The first one is that dominance checking now forces a constant case label to appear before a guarded pattern of the same type. It makes it possible for the selector expression to match multiple labels in a switch block. Consider this problematic example:

static void error(Object o) {

    switch(o) {

        case CharSequence cs ->

            System.out.println("A sequence of length " + cs.length());

        case String s ->	// Error - pattern is dominated by previous pattern

            System.out.println("A string: " + s);

It is a compile-time error if a label in a switch block is dominated by an earlier label in that switch block. This means that you can check for bad code in similar situations. \ The second enhancement improves the exhaustiveness checking of switch blocks, making it more precise with sealed hierarchies where the permitted direct subclass only extends an instantiation of the (generic) sealed superclass. In other words, the compiler now not only helps keep your code organized, but now fully understands sealed classes hierarchies, which is another improvement in accordance with Java™ ideology. If you are interested, you really should check out the description of this JEP, as it is not possible to dive deep into this issue without making this article bloated.

JEP 421: Deprecate Finalization for Removal

The only deprecated feature in this release, this JEP sets the Finalization, that was introduced as early as in Java 1.0, for removal and was a constant source of headache for developers for more than 20 years because of the way it was implemented.

To understand the issue we need to get into the way that Java’s built-in automatic memory management works.

There are Garbage Collectors that free memory and this happens behind the scenes. They check for objects that are unreachable. And when the garbage collector decides that they are no longer needed it frees their memory. The problem is that some of these objects represent resources provided by the operating system such as an open file descriptor or block of native memory. For them reclaiming heap memory is not enough, the program has to release the underlying resource back to the operating system. So in case it does not happen, the resources are leaked - they are still considered in use by the OS and therefore are not freed.

As the application works the number of such leaks grows and they create vulnerabilities or just crash the program.

The finalization was invented as a way to get rid of leaks, but unfortunately it did not work that great because of unpredictable and unconstrained behavior.

Not recommended for use for some time, now it is deprecated for removal. The process will take some time, because this function is used in many applications and standard Java API. Alternative mechanisms are try-with-resources statement introduced in Java 7 and explicit Cleaners introduced in Java 9.

But the transition process could take a long time, as many libraries and even JDK itself utilize finalizers profusely.

Conclusion

The good news is that Java 18 does not only enhance the previously implemented features, but introduces a surprisingly vast amount of innovations. It seems that the reasons to migrate to the latest version keep arising, and with Java 8 being almost 8 years old, now is the good time to start considering updating to the latest LTS release. And while even Java 6 and 7 are still supported by BellSoft, the release of Java 18 provides a lot of motivation to at least test it, possibly by starting the new project with BellSoft tiny Docker containers.

Subcribe to our newsletter

figure

Read the industry news, receive solutions to your problems, and find the ways to save money.

Further reading