What is new in Java 18
Java 18 was released in March 2022 aiming to bring new features and enhancements for the Java community along with some preview features. Let us delve into these features.
1. JEP 400: UTF-8 by Default
When working with file writing, reading, and text processing in Java, it’s common to provide a charset as a parameter to standard Java APIs. Among the supported charsets are US-ASCII, UTF-8, and ISO-8859-1. If no charset option is explicitly stated, standard Java APIs often default to the system’s default charset. At startup, the JDK determines this default charset based on various environment-dependent factors such as the operating system, user locale, and other considerations. It’s important to note that the default charset may vary across environments, potentially causing challenges for even experienced developers when using APIs relying on this default.
To address potential issues and enhance predictability across different environments (such as Windows or Linux), from Java 19 it is recommended to establish a widely accepted charset, such as UTF-8, as the default.
Command Snippet
java -Dfile.encoding=UTF-8
This ensures uniformity and portability in Java programs by utilizing UTF-8 as the default charset when not explicitly specified, and standardizing the use of UTF-8 across SE Java APIs (excluding console I/O).
2. JEP 408: Simple Web Server
Simple Web Server feature in Java 18 primarily serves educational purposes, aiming to enhance the accessibility of the JDK for developers. It achieves this by minimizing activation efforts through the provision of a command-line tool specifically designed to initiate a straightforward web server tailored for static files.
JEP 408 introduced a command-line tool, jwebserver, designed to launch a basic web server catering to the serving of static files. Ideal for prototyping, informal coding, and testing, this tool is particularly well-suited for students. It proves valuable in scenarios where a local testing server is necessary to replicate a client-server setup during web development testing. Additionally, jwebserver
comes in handy when utilizing static files as API stubs arranged in a directory structure mirroring RESTful URLs, containing dummy data for web service or application testing. Another useful application arises in cases of informal file browsing and sharing across systems, such as exploring a distant server’s directory from your local PC.
When executed, jwebserver
defaults to initiating a simple web server on port 8000
. It serves static files from the directory where the command is initiated.
Terminal Output
./jwebserver Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::". Serving C:\Users\yatin.batra\MyCode and subdirectories on 127.0.0.1 port 8000 URL http://127.0.0.1:8000/ 127.0.0.1 - - [10/Nov/2022:18:59:22 +0800] "GET / HTTP/1.1" 200
It’s important to note that the server accommodates only HEAD and GET requests, responding to other requests with either a 501 – Not Implemented or a 405 – Not Allowed error message.
In case you need to start the jwebserver
on a different port you can use the -p
attribute.
Command Snippet
./jwebserver -p YOUR_PORT_NUMBER
jwebserver
server also allows you to serve files from a directory of your choice and this be achieved with the help of -d
attribute.
Command Snippet
./jwebserver -d PATH_TO_THE_DIRECTORY
3. JEP 413: Code Snippets in Java API Documentation
Thorough documentation of code implementation is a crucial element in the development cycle. This entails providing clear and comprehensive explanations for methods, ensuring that other developers can accurately comprehend the author’s intentions during the code-writing process.
The Javadoc
tool in Java interprets the content within the {@code ...}
tag as HTML code. However, this approach has certain drawbacks, such as the inability to incorporate syntax highlighting, the incapacity to include HTML markups and challenges related to indentation. To address these limitations, this JEP introduces the @snippet
tag, providing developers with greater flexibility to include source code snippets in their documentation. Let us take a look at the @snippet
tag introduced in JEP 413:
3.1 Inline Code Snippets
These snippets help in adding the code snippets into a Javadoc comment by explicitly enclosing the code within the @snippet
tag i.e.
Code Snippet
/** * The code below shows the content of {@code welcome()} method * {@snippet : * public void welcome() { * System.out.println("Hello world!"); * } * } */ public class MyClass { public void welcome() { System.out.println("Hello world!"); } }
3.2 External Code Snippets
These snippets help in adding the code snippets into the code from a separate file. To reference an external code snippet in the @snippet
tag add either class
attribute for Java classes or file
attribute for other file types.
Command Snippet
{@snippet class="MyClassSnippet"} {@snippet file="MyProperties.properties"}
Java 18 @snippet
tag also provides a way to specify specific regions within an external file by using the @start
and @end
tags and matching on id. Let us understand this with a short example.
Code Snippet
public class JcgWorld { public static void main(String[] args) { // @start region="main" System.out.println("Hello World!"); } // @end region="main" } /** * {@snippet class="JcgWorld" region="main"} */ ….
4. JEP 416: Reimplement Core Reflection with Method Handles
JEP 416 is a direct result of the apprehension regarding an impending maintenance challenge. Since the beginning of Method handles in Java 8, there have been three avenues for executing reflective operations:
- Native VM methods
- Stubs dynamically generated by the compiler
- Method handles
Considering the forthcoming changes expected from Project Valhalla, such as the introduction of value objects/primitive classes, maintaining three distinct branches of reflection code would become a necessity.
5. JEP 417: Vector API (Third Incubator)
A vector computation involves a sequence of operations conducted on vectors. A vector, consisting of a predominantly predefined set of scalar values, corresponds to the number of hardware-defined vector lanes. JEP 417 provides an API for developers to leverage CPU architectures that provide scalable vector extensions. This will lead to enhanced performance compared to equivalent computations on non-extended processors. More details about JEP 417 can be found on the Java 17 release page.
6. JEP 418: Internet-Address Resolution SPI
The inclusion of the capability to manage internet address resolution in the JDK is a noteworthy addition. This enhancement empowers developers to register a ServiceProvider responsible for handling hostname to IP resolutions performed by the InetAddress classes.
The objective of JEP 418 is to establish a service-provider interface (SPI) to handle the resolution of host names and addresses for java.net.InetAddress, replacing the usage of the platform’s built-in java.net.InetAddress
resolver.
Code Snippet
InetAddress name = InetAddress.getByName("javacodegeeks.com");
The java.net.InetAddress
API is responsible for converting host names to IP addresses and vice versa. JEP 418 redesigned java.net.InetAddress
resolver to use a Service Loader instead of platform built-in capability. Let us take a look at the approach to understand it better:
Code Snippet
// Resolver public class MyInetAddressResolver implements InetAddressResolver { @Override public Stream lookupByName(String host, LookupPolicy lookupPolicy) throws UnknownHostException { return Stream.of(InetAddress.getByAddress(new byte[] {127, 0, 0, 1})); } @Override public String lookupByAddress(byte[] addr) { throw new UnsupportedOperationException(); } } // Provider public class MyInetAddressResolverProvider extends InetAddressResolverProvider { @Override public InetAddressResolver get(Configuration configuration) { return new MyInetAddressResolver(); } @Override public String name() { return "Internet Address Resolver Provider."; } }
7. Deprecate Finalization for Removal
Since Java 1.0, Finalization has been in place to assist in preventing resource leaks. It enables classes to implement a finally
method to release system resources, such as file handles or non-heap memory, requested by the operating system.
The garbage collector invokes the finalize()
method before releasing an object’s memory. While this approach seems reasonable, it has revealed some fundamental and critical flaws:
7.1 Performance
- The timing of garbage collector cleanup is unpredictable, potentially causing significant delays or even no invocation of the finalize() method after an object is no longer referenced.
- Full garbage collection can lead to noticeable latency if many objects being cleaned up have
finally
methods. - The
finally
method is called for every instance of a class, regardless of necessity, with no way to specify that individual objects do not require finalization.
7.2 Security Risks
- The
finally
method can execute arbitrary code, posing security risks such as storing a reference to the object to be deleted, preventing its cleanup by the garbage collector. - If an exception is thrown in a class constructor, the object remains on the heap. When later removed by the garbage collector, its
finally
method may operate on an incompletely initialized object or store it in the object graph.
7.3 Error-Proneness
Though a finally
method should always call the finally
method of the parent class, the compiler does not enforce this, potentially leading to resource leaks if a class is extended and the overridden finally
method is not properly invoked.
7.4 Multithreading
The finally
method is executed in an unspecified thread, requiring maintenance of thread safety for the entire object, even in applications without multithreading.
7.5 Alternatives to Finalization
Several alternatives to Finalization are available:
- The
try-with-resources
feature, introduced in Java 7, automatically generates afinally
block for classes implementing theAutoCloseable
interface. This block calls the correspondingclose()
methods. Static code analysis tools such as SonarQube etc commonly identify and flag code lackingAutoCloseable
objects withintry-with-resources
blocks.Code Snippet
try (FileInputStream input = new FileInputStream(inputFile); FileOutputStream output = new FileOutputStream(outputFile)) { // Rest of the code. }
- Java 9 introduced the Cleaner API, allowing the registration of Cleaner Actions. These actions are invoked by the garbage collector when an object is no longer accessible, extending beyond memory reclamation.
Cleaner actions lack direct access to the object itself, eliminating the possibility of storing a reference. Registration is necessary only when a specific object requires such actions, and the calling thread for these actions can be determined.
Given these alternatives and their availability, the finalize()
methods in Object and various other classes within the JDK class library were marked as “deprecated” in Java 9.
8. EP 419: Foreign Function & Memory API (Second Incubator)
Java 17 introduced the Foreign Function & Memory API, a culmination of the Foreign Memory Access API and the Foreign Linker API, both of which underwent various incubator phases. This newly developed API is part of Project Panama and aims to supersede JNI (Java Native Interface), a component integrated into the platform since Java 1.1. JNI facilitates the invocation of C code from Java, but its implementation is widely recognized as intricate, error-prone, and slow.
The primary objective of the Foreign Function & Memory API is to streamline the implementation process by up to 90% and enhance API performance by a factor of 4 to 5.
9. JEP 420: Pattern Matching for Switch (Second Preview)
Pattern matching is a feature of Java 17 and it simplifies the syntax for common coding patterns and enhances the expressiveness of code. It allows for more concise and readable code when working with data types. Here’s a brief example of how pattern matching might be used with switch
in Java 17:
Code Snippet
public class MyExample { public static void main(String[] args) { Object obj = "Hello"; switch (obj) { case String s -> System.out.println("It's a String: " + s); case Integer i -> System.out.println("It's an Integer: " + i); case Double d -> System.out.println("It's a Double: " + d); default -> System.out.println("It's something else"); } } }
In this example, the switch
statement uses the arrow (->
) syntax for pattern matching. Each case
checks if the object matches a specific type and extracts the value if it does. The default
case handles other cases.
In JEP 420 following improvements have been made:
- For the sake of readability, dominance checking now enforces that a constant case label precedes a guarded pattern of the same type.
- Enhanced definitions for the exhaustiveness of switch blocks.
Code Snippet
static int codeCoverage(Object obj) { return switch (obj) { case String s -> s.length(); case Integer i -> i; default -> 0; }; }
10. Conclusion
The latest advancements in Java, as evidenced by Java Enhancement Proposals (JEPs), showcase the continuous evolution of the programming language. JEP 400 marks a significant step forward with UTF-8 becoming the default character set, enhancing internationalization support. JEP 408 introduces a Simple Web Server, simplifying the process of deploying web applications. JEP 413 enhances the Java API Documentation by allowing code snippets, improving clarity and usability for developers. JEP 416 takes a crucial step by reimplementing Core Reflection with Method Handles, enhancing performance and maintainability. The third incubation of JEP 417 brings the Vector API, empowering developers with powerful operations on vectors. JEP 418 introduces an Internet-Address Resolution SPI, contributing to the extensibility of the platform. The Foreign Function & Memory API, incubated for the second time in JEP 419, promises a more efficient and less error-prone alternative to JNI. Lastly, JEP 421 paves the way for the deprecation of finalization, aligning with efforts to mitigate its inherent performance, security, and error-prone drawbacks. These collective endeavors underscore Java’s commitment to modernization, performance improvement, and developer-friendly enhancements, reinforcing its position as a robust and forward-looking programming language.