Part 25: Java 9 Platform Enhancements – JShell, Private Interface Methods, Process API, Try-with-Resources, Multi-Release JARs & jlink

Introduction

Java 9 is often remembered for one major feature:

The Java Platform Module System (JPMS).

However, Java 9 introduced many additional enhancements that improved the daily experience of Java developers.

Some of these improvements solved long-standing language limitations.

Others modernized the Java platform itself.

Many of these features quietly became part of everyday enterprise development, even though they rarely receive the same attention as Streams or Lambdas.

In this article, we’ll explore the remaining major features introduced in Java 9 and understand how they fit into modern enterprise applications.


Learning Objectives

By the end of this article, you will be able to:

  • Use JShell for rapid experimentation.
  • Understand private methods in interfaces.
  • Work with the enhanced Process API.
  • Simplify resource management.
  • Understand multi-release JARs.
  • Build custom Java runtimes using jlink.
  • Apply these features in enterprise environments.

JShell – The Java REPL

The Problem Before Java 9

Before Java 9, trying a few lines of Java required:

  1. Create a class.
  2. Add a main() method.
  3. Compile.
  4. Run.

Example:

public class Test {

    public static void main(String[] args){

        System.out.println("Hello");

    }

}

For small experiments, this workflow was cumbersome.


Java 9 Solution

JShell introduced a Read-Evaluate-Print Loop (REPL).

Simply start:

jshell

Now execute Java statements directly.

jshell> int x = 10;

jshell> int y = 20;

jshell> x + y

Output

30

No compilation step.

No main() method.


Enterprise Uses

JShell is useful for:

  • Learning Java
  • Trying Stream pipelines
  • Testing algorithms
  • Exploring APIs
  • Interview preparation
  • Debugging small snippets

It is not intended to replace IDEs or build tools for production applications.


Private Methods in Interfaces

In Java 8, interfaces gained default methods.

However, developers quickly noticed duplicated code.

Example:

public interface PaymentService {

    default void process(){

        validate();

        log();

    }

    default void refund(){

        validate();

        log();

    }

}

The validation and logging logic often had to be repeated.


Java 9 Solution

Interfaces can now declare private helper methods.

public interface PaymentService {

    default void process(){

        validate();

    }

    default void refund(){

        validate();

    }

    private void validate(){

        System.out.println("Validation");

    }

}

This improves maintainability without exposing implementation details.


Private Static Methods

Java 9 also introduced private static methods.

private static void log(){

    System.out.println("Logging");

}

Useful for reusable helper functionality shared across default and static methods.


Enhanced Process API

Before Java 9

Managing operating system processes was limited.

Process process =

        Runtime.getRuntime()

                .exec("java");

Obtaining process metadata or interacting with child processes was cumbersome.


Java 9 Solution

The new Process API provides much richer capabilities.

ProcessHandle.current();

Retrieve the current process.

Example:

ProcessHandle.current()

        .pid();

Returns:

Current Process ID

Process Information

ProcessHandle.current()

        .info();

Provides information such as:

  • Command
  • Start time
  • User
  • Arguments

Enterprise Uses

Useful for:

  • Monitoring
  • Container environments
  • Diagnostics
  • Health checks
  • Administrative tools

Try-With-Resources Enhancement

Java 7

BufferedReader reader =

        new BufferedReader(...);

try(reader){

    ...

}

Actually, Java 7 required the resource to be declared inside the try statement:

try (BufferedReader reader = new BufferedReader(...)) {

    ...

}

Java 9

Existing effectively final variables can be used directly.

BufferedReader reader =

        new BufferedReader(...);

try(reader){

    ...

}

Cleaner.

Less duplication.


Diamond Operator Improvements

Java 9 expanded support for the diamond operator in anonymous inner classes.

new HashMap<>() {

}

This reduced verbosity in some advanced use cases while preserving type safety.


Multi-Release JARs

One of Java 9’s lesser-known but powerful features.

Suppose a library wants to support:

  • Java 8
  • Java 11
  • Java 17

without maintaining three separate JARs.

Java 9 introduced Multi-Release JARs.

Structure:

my-library.jar

META-INF

    versions

        9

        11

        17

The JVM automatically loads the implementation appropriate for the running Java version.


Enterprise Uses

Useful for:

  • Framework authors
  • Library maintainers
  • SDK providers

Most business applications consume these libraries rather than creating multi-release JARs themselves.


jlink

Traditional Java deployments included an entire JDK or JRE.

Often, applications required only a subset of Java modules.

Java 9 introduced:

jlink

which creates custom runtime images containing only the required modules.

Example:

Application

+

Required Modules

↓

Custom Runtime Image

Benefits:

  • Smaller deployments
  • Faster startup
  • Reduced attack surface
  • Simpler distribution

Enterprise Uses

jlink is particularly valuable for:

  • Docker images
  • Embedded devices
  • Microservices
  • Cloud deployments
  • Appliance software

Smaller runtime images can reduce container size and deployment time.


Platform Improvements

Java 9 also included many under-the-hood enhancements.

Examples include:

  • Improved startup performance.
  • Better garbage collection infrastructure.
  • Internal API encapsulation.
  • Cleaner modular JDK architecture.

Although invisible to application developers, these changes laid the foundation for later Java releases.


Enterprise Migration Strategy

For most enterprise teams upgrading from Java 8:

  1. Upgrade the JDK.
  2. Resolve deprecated API usage.
  3. Continue using the classpath initially.
  4. Evaluate JPMS when appropriate.
  5. Take advantage of language and library improvements immediately.

This incremental approach minimizes migration risk.


Common Mistakes

Treating JShell as a Production Tool

JShell is designed for experimentation and learning, not application deployment.


Ignoring jlink

Organizations deploying many microservices can benefit significantly from custom runtime images.

Evaluate whether runtime size and startup improvements justify adoption.


Overusing Private Interface Methods

Private interface methods should support default or static methods, not replace proper service abstractions.


Best Practices

✔ Use JShell for experimentation and learning.

✔ Extract repeated default method logic into private interface methods.

✔ Use the enhanced Process API for diagnostics and monitoring.

✔ Prefer the simplified try-with-resources syntax when applicable.

✔ Consider jlink for containerized deployments.

✔ Use multi-release JARs only when maintaining libraries across multiple Java versions.


Interview Questions

What is JShell?

A Read-Evaluate-Print Loop (REPL) introduced in Java 9 for interactively executing Java code.


Why were private interface methods introduced?

To eliminate duplicated code shared by default and static interface methods.


What problem does jlink solve?

It creates custom Java runtime images containing only the modules required by an application.


What is a Multi-Release JAR?

A JAR that contains version-specific class implementations, allowing the JVM to load the most appropriate implementation for the running Java version.


What changed in try-with-resources in Java 9?

Effectively final resources declared outside the try statement can now be used directly within it.


Summary

Java 9 delivered far more than modules. Features such as JShell, private interface methods, the enhanced Process API, simplified try-with-resources, multi-release JARs, and jlink collectively improved developer productivity and modernized the Java platform.

Many of these enhancements work behind the scenes, but they have become essential building blocks for today’s Java ecosystem, particularly in cloud-native and containerized environments.

With Java 9 complete, we can now move to the next release, where one seemingly small feature dramatically changed how Java developers write local variable declarations.


Coming Up Next

Part 26 – Java 10: Local Variable Type Inference (var) – Cleaner Code Without Losing Type Safety

We’ll examine:

  • Why var was introduced
  • How type inference works
  • Where var can and cannot be used
  • Readability guidelines
  • Enterprise coding standards
  • Common anti-patterns
  • Performance myths
  • Best practices for Spring Boot and microservices

Leave a Reply

Your email address will not be published. Required fields are marked *