Introducing JShell: A Guide for Using the New Java 9 Feature

Jasmin Kurtanović, Software Engineer

Tech

05.06.2020.

featured image

The shell or the REPL (read-eval-print-loop) is a well-known tool in many programming languages. Typically, this is more common in scripting languages such as Python or Node, but more recently it’s been adopted by JVM languages like Clojure and Groovy as well. The upcoming Java 9 release finally brings this shell functionality to the Java language as well, in the form of JShell. This blog post is a preview of the use of the new feature java 9 Jshell. More details about it you can find at web sites that are used as a source: Introduction Jshell and Tutorial Jshell.

What Is a REPL (ReadEvalPrint Loop)?

Simply put, the REPL is an interactive shell into which we can enter commands and have these immediately executed and the results displayed.

The use of this tool can greatly help when trying out new ideas and techniques and when quickly testing code without having to write an entire test class to run.

At its core, this is all about an immediate feedback loop, so it can have a significant impact on productivity in that particular language.

Why Use JShell?

When using JShell, you can enter your program elements one at a time, immediately see the result, and make adjustments as needed.

Java program development typically involves the following process:

  • Write a complete program.
  • Compile it and fix any errors.
  • Run the program.
  • Figure out what is wrong with it.
  • Edit it.
  • Repeat the process.

JShell helps you try out code and easily explore options as you develop your program. You can test individual statements, try out different variations of a method, and experiment with unfamiliar APIs within your JShell session. JShell doesn’t replace an IDE. As you develop your program, paste code into JShell to try it out, and then copy and paste the working code from JShell into your program editor or IDE.

What is JShell Good For?

  • Exploring a new API or language feature (Experiment and instantly see results)
  • New to Java, new to programming (Start with expressions vs classes, immediate feedback)
  • Prototyping (Write complex code incrementally)

JShell Architecture

Before we dive into the commands, let’s look under the hood and see how it works. Whenever we execute a piece of code (a snippet), we first interact with the command line interface. The JShell implementation is built on top of the javac compiler and interacts with the command line through the JShell API. The execution of the generated bytecode is done to a remote JVM instance. The Java Debug Interface is responsible for sending the bytecode to the JVM. The thought process behind this architectural approach is that if the JVM crashes, your application will not be affected. After the code is executed, the result is sent back to the command line interface through a socket.

JShell Architecture Scheme

Hello Serengeti

We'll be using Java 11 in this blog in order to take advantage of the var keyword, so make sure you have at least Java 11 installed to follow along throughout this blog tour.

JShell is easily started by typing jshell into the command line. You'll be presented with a welcome message and shell waiting for you to input commands or any valid Java expression.

Welcome to JShell

Let's execute our first command. At the shell prompt, type var greeting = “hello” and press . You should see get an output like this:

JShell hello

You'll notice that it echoes the value of the greeting, confirming that the value is now equal to hello. You may also have noticed that you didn't need to end the expression with a semicolon. A small but nice feature!

In order to complete our greeting, we need an audience. Type var audience = “Serengeti” and press . This time, JShell recognizes that you're not finished with your expression and allows you to continue on the next line. Finish your expression by typing "Serengeti" followed by . Just like before, JShell echoes the value confirming that it has been set.

JShell audience

Tab Completion

One of the first things you'll notice is the nicely integrated tab completion. Let's concatenate our greeting and audience strings into a new variable called saying. Start by typing var saying = gr and then press . You'll see that the greeting variable is automatically completed. Do the same with the audience variable and press enter to see the result of the concatenation.

JShell greetings and audience

Tab completion works just as you'd expect, automatically completing values that are unique or providing potential values when it's ambiguous. It works on any previously typed expressions, objects, and methods. Note that it does not work on built-in keywords.

If you wanted to make the saying variable all uppercase but you couldn't remember the exact name of the method, you could simply type saying.to and then press tab to see all the valid possible methods that start with to, as so:

JShell Saying to

Control Flow Statements (if-else, while loops, for loops)

You can also write multi-line control flow statements in the REPL. JShell is smart enough to recognize multi-line statements and prompts with a…> symbol to let you enter the next line of the statement. The following is an example of an If-Else statement:

JShell Control Flow Statements

And, here is how you can use the while loop in the REPL:

JShell Loop in the RELP

Finally, the following is an example of a for-loop:

JShell Loop example

Defining and Invoking Methods

You can define methods in the REPL similar to how you define them in Java classes:

JShell Define Java Classes

Once a method is created in a JShell session, you can call it anytime until you quit that session:

JShell Call it anytime

Creating Classes and Objects

You’re not just limited to simple statements and functions. You can also create classes, interfaces and enums in JShell:

JShell Create Classes
JShell Create Interfaces
JShell cerate enums

Exploring JShell Commands

Apart from running Java language expressions and statements, JShell also provides some meta-commands to help you play around with the REPL environment.

You can use these commands to list the variables, methods, and imports available in the current JShell session, view the history of what you have typed, edit an already defined variable or method, save your workspace and open any existing workspaces.

Type /help or /? to get a list of all the available commands. Let’s look at some of these commands:

  • /imports – List all available imports

    JShell imports some of the most used and important Java packages by default when you start a session.

    Type /imports  to get a list of all these imports.

    JShell Command import
  • You can import additional packages in a JShell session like this

    JShell Command Import Additional Packages
  • /vars – List all the variables defined in the current JShell session

    /vars lists all the variables that are declared in the current JShell session along with their value:

    JShell Command Vars
  • /methods – List all the methods defined in the current JShell session

    JShell Command Methods


  • /edit – Edit an already defined method, variable or class

    You can edit an already defined method or variable using the /edit command. In the following example, I’m editing the sum() method that we have defined earlier.

    JShell Command Edit
  • /save – Save the current workspace to a file
    You can save the whole source code that you have typed in the current JShell session in a file using the /save command

    JShell Command Save
  • /open – Open an already saved workspace

    The /open command allows you to open a file as the source input for the current JShell session
    Apart from loading snippets and commands from external files, you can also use the /open command to load a class in the JShell session from an external file.

    JShell Command Open
  • Assuming you have defined a class named ExampleClass in the current working directory, here is how you can load the class in JShell:

    JShell Command Example Class

Exception Handling

Anytime we run a command in JShell that ends up in an Exception reaching the top of the stack, this is automatically handled by displaying the stack trace, including all line numbers, similar to how Java typically handles exceptions.

This can be quite helpful for easily diagnosing problems:

JShell Expectations Handling

This tells us an exception was thrown on line 3 of the test() method, which itself was command 1 of the script. Therefore, we can immediately see what the offending statement was. Unfortunately, the lack of line numbers means that this is easiest when we have short functions to work with, which is, of course, good practice anyway.

Summary

JShell is definitely one of the coolest features of Java 9. It helps beginners get a grasp of the language quickly. Moreover, it helps other developers run quick experiments without writing classes, methods, imports and all that boilerplate. 

Most modern languages and tools can be interacted with via a shell. Finally, starting with Java 9, so can the Java language itself – a feature that was missing for many years.

JShell is a fantastic tool that has a wide variety of uses. Naturally, the tool is most useful for quickly testing out some code to see how it works without needing to write an entire class, compile it and run it first.

This can greatly improve productivity when developing our code, and shorten the feedback cycle on testing things out.

RELATED

01.06.2020.

Blazor WebAssembly

This article touches on the WebAssembly hosting model. This model makes development much easier with its use of CSS, HTML and C# without any need for JavaScript. It can adapt to user needs of being tied to a specific app hosting model. User interface events are triggered and executed directly in the browser. In order to create new applications with this framework in the WebAssembly version, you need to have Visual Studio Preview 2019 with the latest ASP.NET and web development workload.

Read more