Core Java

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 a finally block for classes implementing the AutoCloseable interface. This block calls the corresponding close() methods. Static code analysis tools such as SonarQube etc commonly identify and flag code lacking AutoCloseable objects within try-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.

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

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

0 Comments
Inline Feedbacks
View all comments
Back to top button