During his JavaOne 2016 keynote, Mark Reinhold, Chief architect of the Java platform group pointed out that Java 9 is much bigger than Jigsaw as can be seen in the 85 JEPs targeted for Java 9. I would like to discuss one new Java feature he highlighted, JEP 222, the Java shell (also known as JShell.)
With JShell, Java 9 will enable developers to use Read-Eval-Print loop (REPL) which is an interactive tool that evaluates user input and prints the output either as a value or a state change.
What’s JShell?
JShell is an API and a tool that helps evaluate code snippets. A snippet has to correspond to Java Language Specification (JLS) syntax productions. JShell also evaluates queries and commands. It differentiates commands from snippets by a leading slash as can be seen in the following example:
jshell> /import
| import java.util.*
| import java.io.*
| import java.math.*
| import java.net.*
| import java.util.concurrent.*
| import java.util.prefs.*
| import java.util.regex.*
A JShell state is modeled after a JVM instance. JShell will employ the Compiler API for code analysis, tab-completion, and parsing of raw snippets amongst other things and will use the Java Debug Interface (JDI) for code replacement.
The user could also use batch scripts if they like to circumvent the interactive interface.
JShell Demo At JavaOne
Before I go into the demo presented by Reinhold at JavaOne, I wanted to note that if you get the latest version of Java 9 JDK, and type java –version
, you would note a change in the way the version string is now expressed, as shown below:
$ java -version
java version "9-ea"
Java(TM) SE Runtime Environment (build 9-ea+136)
Java HotSpot(TM) 64-Bit Server VM (build 9-ea+136, mixed mode)
This is in contrast to the older format:
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
The change comes about due to the new scheme introduced by JEP 223. The version string is now more parse-able and also more in-line with the current industry practices as highlighted by Semantic Versioning. The new scheme helps with easy identification of a major, minor or a security-update release.
In the example shown above, the pre-release identifier (ea
– read as “early access”) is preceded by a “-” and then followed by a “+” and then the build number (136
) of the promoted build.
Coming back to the demo, if you type “jshell
“ on your command line, you will get a JShell prompt as can be seen below:
$ jshell
| Welcome to JShell -- Version 9-ea
| For an introduction type: /help intro
jshell>
If you type a simple String declaration as seen here, you will be able to explore the methods that can be invoked (including overloaded methods):
jshell> String x = "foo bar baz"
x ==> "foo bar baz"
jshell> x.
charAt( chars() codePointAt(
codePointBefore( codePointCount( codePoints()
compareTo( compareToIgnoreCase( concat(
contains( contentEquals( endsWith(
equals( equalsIgnoreCase( getBytes(
getChars( getClass() hashCode()
indexOf( intern() isEmpty()
lastIndexOf( length() matches(
notify() notifyAll() offsetByCodePoints(
regionMatches( replace( replaceAll(
replaceFirst( split( startsWith(
subSequence( substring( toCharArray()
toLowerCase( toString() toUpperCase(
trim() wait(
jshell> x.substring(4,7)
$3 ==> "bar"
jshell> Arrays.asList(x.split(""))
$5 ==> [f, o, o, , b, a, r, , b, a, z]
jshell> Arrays.asList(x.split(" "))
$6 ==> [foo, bar, baz]
Above example shows some temporary variables ($3, $5, $6) that can be used to evaluate further expressions as needed.
jshell> import java.util.stream.*
jshell> $6.stream().filter(s -> s.startsWith("b")).collect(Collectors.toList())
$9 ==> [bar, baz]
In the above example we imported java.util.stream
package to be able to tab and get a list of methods for Collectors class.
Conclusion
JShell brings to Java REPL, a very useful feature of the classic LISP-machine. It helps developers with being able to debug code snippets without going through the entire compile, run + debug cycle.