Java 18 Features: Deprecating Finalizers, Simple Web Server and UTF-8 by default

Oskar
5 min readMar 7, 2022

--

Photo by Harry Grout on Unsplash

Java 18 is going globally available on March 22.2022.

As we have gotten used to in the prior releases, many features in the 18 are overlapping with Java 17 ones, but as a next iteration in the feature preview cycle, after the feedback was collected by the community, and acted upon, over the last six months.

Project Panama’s Vector API is getting into Third Incubator and Pattern Matching for switch is getting into Second Preview. I wrote about the new ways of using switch and its implications in my Java 17 blog a few months back, I’d advice you to take a look at that, if haven’t already, since it’s not an insignificant change.

As for the brand new changes, as always, the release notes are quite extensive. Most notable changes likely are defaulting to UTF-8 when charset is not specified, a new capability in java doc @snippet used for adding example code snippets, deprecating for removal multiple Java Finalization mechanisms and the new command-line tool for starting a simple web server for the experimentation purposes (not intended for production use).

Deprecating for Removal Finalization

In the last decades, for better or worse, one of the opening questions in the technical interviews was to list and explain all of the methods that originate from the Object class. The world is changing, and Java with it, so the answer to this life long question soon will be different than it was in the last 3 decades.

All jokes aside, Object.finalize() is not the only one getting deprecated for removal, most legacy finalization mechanisms are, here is the full list:

  • java.lang.Object.finalize()
  • java.lang.Enum.finalize()
  • java.awt.Graphics.finalize()
  • java.awt.PrintJob.finalize()
  • java.util.concurrent.ThreadPoolExecutor.finalize()
  • javax.imageio.spi.ServiceRegistry.finalize()
  • javax.imageio.stream.FileCacheImageInputStream.finalize()
  • javax.imageio.stream.FileImageInputStream.finalize()
  • javax.imageio.stream.FileImageOutputStream.finalize()
  • javax.imageio.stream.ImageInputStreamImpl.finalize()
  • javax.imageio.stream.MemoryCacheImageInputStream.finalize()

The main goal of Finalization, which has added in the Java version 1, is to avoid resource leaks. While garbage collector will clean up memory from the heap when object is not needed any more, it can’t release the resource (like an open file descriptor) provided by the operating system so you’l always have to explicitly call stream.close() in the finalizer block.

That being said, why are the above mentioned finalizers being removed from the language? To sum it up: it’s really a hard programing model. It promotes one of the main things that you don’t want to stress about, and that is a manual memory management.

When James Gosling was developing Java at Sun in the 1990 he wanted to fix in Java (at the time called Oak language) all the downfalls he was facing working with C and Cpp. One of the must-have features was garbage collector and enjoying fully automatic memory management. Not just because managing memory manually is devious and error prone but also, at that time, a study was done to unveil what causes the most amount of security vulnerabilities in software. Turned out that two thirds of all security vulnerabilities in C software was caused by the pointer magic. Mr Gosling really wanted to fix that in Oak.

So, what are the alternatives? Oracle hopes that most of our use cases will be cover by the try-with-resources construct released way back in Java 7. Try-with-resources does quite a better, well mainly less verbose, job in releasing resource that is not needed any more than try-finally does, and most times changing try-finally to try-with-resources will be a simple refactor.

For more complicated examples, where you need more control, Cleaners Api released in Java 9 is there to help you. While verbose, cleaners can fully replace what the old finalizers did, so in more complex use cases when try-with-resources is not sufficient, Cleaner Api is your friend (and while relatively unknown, it’s been out for a while so it’s battle tested and reliable).

As Oracle team has stated, this will be a lengthy transition since every highly used library and even the JDK itself makes significant use of finalizers, some of them have been converted to Cleaners but many have not yet (at the time of writing this). In any case you should be ready, and at least analyze how much work will your software require to transition away from finalizers.

Code Snippets in Java Docs

In Java Doc there is a new inline tag @snippet that is used to declare code fragments. Example from the official JEP:

/**
* The following code shows how to use {@code Optional.isPresent}:
* {@snippet :
* if (v.isPresent()) { // @highlight substring="v"
* System.out.println("v: " + v.get());
* }
* }
*/

In the snippet you can import or reference code from the other files. Snippets support modifying example code by highlighting arbitrary words, replacing or linking parts of the code and many neat features.

Simple Web Server

Simply put, Java 18 adds a new command line tool named jwebserver.

Usage example: jwebserver -p 9000

Running the command fires up a simple web server that serves static files from the current directory. You can define a custom port via -p and a custom directory via -d.

Right now the server is only intended for education, experiments, testing and similar, it’s not intended for the production usage.

UTF-8 by Default

Whenever using a standard Java API to process text one of the arguments available for passing is a charset. When not explicitly passed Java will use the default charset, which means that the JDK chooses the default charset at startup based upon the run-time environment: the operating system, the user’s locale, and other factors.

That is changed, when not specified explicitly, the default charset that JDK will now pick for you is always UTF-8.

Since UTF-8 has forever been the most common charset used on the internet, this is a very nice change for the sake of unifying behaviors and being platform agnostic.

At the same time this might be a very breaking change for you, so make sure to test your text (json, xml, any text) processing code to make sure that it works as expected after this change, especially if your software has hefty internationalization capabilities.

While non LTS releases rarely pick up much traction, this one seems to lay the ground work for fundamental changes in the years to come. So, have a fun time experimenting with Java 18!

--

--