Introducing JShell and Its API

One of the new features in Java 9 is called ‘JShell’ and it’s awesome. It is basically a Read–Eval–Print Loop (REPL) implementation for the Java language.

You can run JShell in a command line environment (command prompt (cmd) on Windows, Terminal on Mac). If your JAVA_HOME path is set correctly, you could simply type in ‘jshell’ and hit enter. You can find the executable in the jdk-9.jdk/Contents/Home/bin directory.

JShell in Terminal
A launched Terminal instance with JShell running.

Imports

A good thing to keep in mind is the fact that a freshly opened session comes with multiple imports:

jshell> /imports
|    import java.io.*
|    import java.math.*
|    import java.net.*
|    import java.nio.file.*
|    import java.util.*
|    import java.util.concurrent.*
|    import java.util.function.*
|    import java.util.prefs.*
|    import java.util.regex.*
|    import java.util.stream.*

You might as well add any other import. Syntax: import your.package.name.

Expressions and Variables

Since JShell is a Java interpreter, any valid Java expression will be accepted. Find an example expression testing String equality.

jshell> "Hello".equals("World")
$1 ==> false

The result in this obvious example returns false. Note that a variable $1 has been created as well. Execute a similar expression again and you’ll see another variable has been created. Notice the incremental naming ($2 and so on). Creating your own named variables is as easy as:

jshell> String myVariable = "awesome"

Keeping track of all your variables can be done using the /vars command:

jshell> /vars
|    boolean $1 = false
|    boolean $2 = false
|    String myVariable = "awesome"

Methods

Creating or replacing methods is done simply by inputting the entire method definition. Below example creates a method to print any given String and executes it afterwards.

jshell> void printSomething(String s) { System.out.println(s); }
|  created method printSomething(String)

jshell> printSomething("Hi there!")
Hi there!

Listing methods can be done in a way similar to listing variables, using the command /methods.

If you have a long method to edit, I invite you to use /edit <nameOfMethod>. This will open an external editor that is slightly easier to work with for long snippets. Use /edit without parameters to edit the entire anything in the current state. To reset your entire JShell state, use /reset.

Scripting

Have bigger snippets to evaluate? Consider playing around with scripts, which have the <script>.jsh format. To create a script you could simply create a file from scratch or you could issue the command: /save mySnippets.jsh, which saves your current state into the given file.

Say our mySnippets.jsh looks like this:

"Hello".equals("World");
$1 == true
System.out.println("$1 is " + $1 + " and $2 is " + $2)
String myVariable = "awesome";
void printSomething(String s) { System.out.println(s); }
printSomething("Hi there!")

Then we could run (load) it using the /open command.

jshell> /open mySnippets.jsh
$1 is false and $2 is false
Hi there!
awesome

Plenty more advanced stuff you could do with JShell scripts. You might as well be interested in setting a particular script as your starting state, but I’ll leave that as an exercise for the reader.

JShell API

Interpreting Java code within a Java application is now possible using Java 9’s built-in jd.jshell API! Use it for small code evaluations or to run scripts.

I won’t go over this part in depth, because it’s rather self explanatory. However I’ll give a very basic example (you could’ve probably figured out on your own).

import java.util.List;
import jdk.jshell.JShell;
import jdk.jshell.SnippetEvent;

public class Main {

    public static void main(String[] args) {
        try (JShell js = JShell.create()) {
            int yearsOld = 5;
            List<SnippetEvent> snippetEvents = js.eval("String.format(\"I'm %d years old!\", " + yearsOld + ")");
            snippetEvents.forEach(snippetEvent -> System.out.println(snippetEvent.value()));
        }
    }
}

To run scripts, I’ll gladly refer to DZone’s article to get you started extremely quickly. In their code sample you will be able to run any script you provide to their executor implementation. It also comes with some basic event handling (handling failing evaluations). However running their example I noticed that all statements in the provided script must end with a semicolon, otherwise your output might end up looking like Evaluation failed : Snippet:ErroneousKey#1-"Hello".equals("World").

Conclusion

The power of instant expression evaluation feedback surely is useful. I can imagine myself using JShell for quick checks on String formats and small stuff like that. Besides that, I like the fact that the the new feature along with its API support scripting. You could have a static code base that calls scripts that can be changed whenever necessary.

Obviously this is just JShell in a nutshell (that could’ve been a great post title as well I reckon!) and there’s much more to it. The purpose of this post was to quickly go over the very basics and to show the new feature to those who hadn’t heard of it yet.

Play around with JShell yourself. You’ll need to install JDK 9. If you haven’t installed it already, go ahead and download it now.