Java 9 Platform Module system and JShell

In this tutorial we list down and discuss some of the new features introduced in Java 9. We will then delve deeper into the Java 9 Platform Module System and JShell in this tutorial and cover the others later. Here’s a list of the new features:

List of new features in Java 9

  1. Java platform module system
  2. JShell – Interactive command line tool
  3. Reactive Streams
  4. Factory method for Collections
  5. Enhancements in Stream, CompletableFuture, java.util.Arrays, Stack walking API
  6. Project coin changes – e.g. private interface methods
  7. Jlink – tool to assemble modules
  8. Documentation updates, HTML5, javadoc search
  9. Process API changes, new internal representation for String
  10. Parser API for Nashorn
  11. MRJAR – Multi Release Jar

In this tutorial we will look at the first two changes, i.e. Java 9 platform module system and JShell. In the next tutorial we will look at the other changes.

Java 9 Platform Module System

Java 9 introduced the concept of modules that allow breaking up a project into logical parts. Modules provide better configuration and greater encapsulation. A module consists of classes and interfaces and a configuration file known as module-info.java. Module A can access only those members of Module B that have been exported by Module B. To specify that Module A needs Module B, we use the ‘requires’ keyword in the Module A configuration file.
Lets look at an example of the module system using a ‘Hello World’ Example.

Example of Java 9 Platform Modules System

We write a class that prints Hello World followed by the name of a person.

package com.st.HelloWorldModule;

import com.st.HelloWorldModuleHelper.HelloWorldHelper;
public class HelloWorld {
    public static void main(String[] args) {
       HelloWorldHelper helper = new HelloWorldHelper();
       System.out.println(helper.decorate(args[0]));
   }
}

Since printing Hello World followed by a name is a fairly complex operation 🙂 , we create a helper class that decorates the name to create the string ‘Hello World Mithil’

package com.st.HelloWorldModuleHelper;

public class HelloWorldHelper {

   public String decorate(String name) {
      return "Hello World "+name;
   }
}

Note that the helper class is in a package called HelloWorldModuleHelper, whereas the HelloWorld class in a package called HelloWorldHelper. Normally, this would work fine. Here’s how we compile and run the class

cd ~/java/java9/modules/HelloWorldModuleHelper
javac -d ~/java/java9/modules/output/HelloWorldModuleHelper com/st/HelloWorldModuleHelper/HelloWorldHelper.java
cd ~/java/java9/modules/HelloWorldModule
javac -cp ~/java/java9/modules/output/HelloWorldModuleHelper/ -d ~/java/java9/modules/output/HelloWorldModule com/st/HelloWorldModule/HelloWorld.java

In line 2 we compile the HelloWorldHelper class and put the class files in output/HelloWorldModuleHelper directory.
In line 4 we compile the HelloWorld class and put the HelloWorldHelper class in the classpath.
To run the HelloWorld class do this:

cd ~/java/java9/modules/output
java -cp .:../HelloWorldModuleHelper/ com.st.HelloWorldModule.HelloWorld Mithil
Hello World Mithil

We run the HelloWorld class and put the Helper in classpath and all works well.
Its time now to introduce modules. We want to create two modules, one for the HelloWorld class and other for the HelloWorldHelper class.
Here’s how the module-info.java class for HelloWorldHelper looks like

module com.st.HelloWorldModuleHelper{
 exports com.st.HelloWorldModuleHelper; 
}

To use this module in HelloWorldModule we will need to use the ‘requires keyword’

module com.st.HelloWorldModule {
	requires com.st.HelloWorldModuleHelper;
}

To specify which modules are included during compilation we specify the –module-path to javac and java

cd HelloWorldModuleHelper
javac -d ../output/HelloWorldModuleHelper com/st/HelloWorldModuleHelper/HelloWorldHelper.java
javac -d ../output/HelloWorldModuleHelper module-info.java

cd HelloWorldModule
javac -d ../output/HelloWorldModule --module-path ../output/HelloWorldModuleHelper/ module-info.java
javac -d ../output/HelloWorldModule --module-path ../output/HelloWorldModuleHelper/ com/st/HelloWorldModule/HelloWorld.java

cd output/HelloWorldModule
java --module-path ~/java/java9/modulesCourse/output -m com.st.HelloWorldModule/com.st.HelloWorldModule.HelloWorld Mithil

In line 3 we compile the module-info.java class, just like any other java class.
In line 6 we include the module path in javac using –module-path.
In line 10 we include the module path in java using –module-path. The result of running this program would be
‘Hello World Mithil’

This is how the directory structure now looks like

Modules_Directory_Structure
Modules_Directory_Structure

If you were to remove the ‘requires’ line from module-info.java, you would see this error:

com/st/HelloWorldModule/HelloWorld.java:3: error: package com.st.HelloWorldModuleHelper does not exist

Java 9 JShell Command line tool.

The JShell tool allows you to write and evaluate Java expressions, statements and declarations on the command line via an interactive tool. To start JShell type in ‘jshell’ on the command line. If that does not work, make sure you have installed JDK 9 or 10 and the bin folder is in classpath. The tool can be primarily used to quickly prototype functions and classes without going through the whole cycle of build, compile and run. Let’s look at some of JShell commands and concepts.

JShell Snippet

A JShell snippet is code that is written in jshell and evaluated independently. It can refer to a variable, method or class declaration, or an actual method call. Here are some examples

int x = 3

This declares an int variable called x. To list all variables use the command /vars>. To declare a class with a static method

public class Test {
public static int sum(int x, int y) {
   return x+y;
}
}

This is how the sum method is run

Test.sum(2,3)

JShell Commands

To list all the methods use /methods and to list all classes use /types.

JShell imports some packages and classes by default. To look at current imports type in </imports. A new import can be directly specified.
To list all the snippets entered so far use the /list command.

JShell Editor

JShell allows editing snippets in an external editor. To specify and editor type in

/set editor vim

To edit snippets type in /edit. To edit a particular snippet type in /edit [snippet_no] . Each snippet is given a number and that number can be use to reference the snippet

JShell shortcuts

JShell defines four shortcuts.

  • Tab – use the tab to autocomplete types, method suggestions or variables.
  • Use Shift+Tab followed by i to auto import. For example, When using java nio PIPE, we need to import the PIPE class. if you type in new PIPE followed by Shift+Tab and i, the tool will suggest imports
    jshell> JFrame
    0: Do nothing
    1: import: javax.swing.JFrame
    Choice: 
    Imported: javax.swing.JFrame
    
  • Shift+tab followed by v can be used to create a variable. In the example above if we fire this command after new JFrame, the tool allows use to define a new jframe variable
    jshell> new JFrame()
    jshell> JFrame jframe = new JFrame()
    
  • Shift+Tab followed by m can be used to create a method from an expression.
    jshell> 2+3
    jshell> int |() { return 2+3; }
    

    enter the name of the method where the cursor(|) is.

The platform module system is a fundamental change to the Java language specification. The JShell tool is a very handy tool for rapid development and prototyping. In the next tutorial, we look at some of the other changes in Java 9.

Leave a Reply

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

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