Conferences are a great place to meet Java luminaries. Devoxx France was one such opportunity to meet Java language architect, ex-colleague and an old friend – Brian Goetz (@briangoetz). We talked about JDK 9 and he was all raving about REPL. He mentioned that even though there are a lot of significant features, such as modularity and HTTP2 client, in Java SE 9, but this tool is going to be talked about the most often. The statement makes sense since it will really simplify exploration of Java APIs, prototyping, demos in conferences, and similar tasks a lot simpler. This blog is coming out of our discussion there and his strong vote on REPL!
Read-Evaluate-Print-Loop has been there in Lisp, Python, Ruby, Groovy, Clojure, and other languages for a while. Unix shell is a REPL which can read shell commands, evaluate them, print the output, and goes back in the loop to do the same thing.
You can read all about REPL in JDK 9 in JEP 222. Summary from the JEP is:
Provide an interactive tool which evaluates declarations, statements, and expressions of the Java Programming Language: that is, provide a Read-Evaluate-Print Loop (REPL) for the Java Programming Language. Also, provide an API on which the tool is built, enabling external tools to supply this functionality.
The motivation is also clearly spelt out in the JEP:
Without the ceremony of class Foo { public static void main(String[] args) { … } }, learning and exploration is streamlined.
JEP 222 targets to ship REPL with JDK 9 but openjdk.java.net/projects/jdk9 does not list it is as “targeted” or “proposed to target”. Seems like a documentation bug 😉
As of JDK 9 build 61, REPL is not integrated, and needs to be built separately. Eventually, at some time before JDK 9 is released, this tool will be integrated in the build.
Lets see what does it require to have it running on OSX. This blog followed Java 9 REPL – Getting Started Guide to build and run REPL. In addition, it provides complete log output from the commands which might be helpful for some.
Lets get started!
Install JDK 9
- Download the latest build, 61 at the time of this writing.
- Setup JAVA_HOME as:
123export JAVA_HOME=`/usr/libexec/java_home -v1.9` - Verify the version:
123456~> java -versionjava version "1.9.0-ea"Java(TM) SE Runtime Environment (build 1.9.0-ea-b61)Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-b61, mixed mode)
Checkout and Install jline2
jline2 is a Java library for handling console input. Check it out:
1
2
3
4
5
6
7
8
9
|
workspaces> git clone git://github.com/jline/jline2.git
Cloning into 'jline2'...
remote: Counting objects: 6419, done.
remote: Total 6419 (delta 0), reused 0 (delta 0), pack-reused 6419
Receiving objects: 100% (6419/6419), 3.23 MiB | 80.00 KiB/s, done.
Resolving deltas: 100% (2945/2945), done.
Checking connectivity... done.
|
And then build it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
jline2> mvn install
[INFO] Scanning for projects...
Downloading: https://repo.maven.apache.org/maven2/org/apache/maven/scm/maven-scm-provider-gitexe/1.8.1/maven-scm-provider-gitexe-1.8.1.pom
Downloaded: https://repo.maven.apache.org/maven2/org/apache/maven/scm/maven-scm-provider-gitexe/1.8.1/maven-scm-provider-gitexe-1.8.1.pom (3 KB at 0.3 KB/sec)
. . .
[INFO] Installing /Users/arungupta/workspaces/jline2/target/jline-2.13-SNAPSHOT-sources.jar to /Users/arungupta/.m2/repository/jline/jline/2.13-SNAPSHOT/jline-2.13-SNAPSHOT-sources.jar
[INFO] Installing /Users/arungupta/workspaces/jline2/target/jline-2.13-SNAPSHOT-tests.jar to /Users/arungupta/.m2/repository/jline/jline/2.13-SNAPSHOT/jline-2.13-SNAPSHOT-tests.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 09:52 min
[INFO] Finished at: 2015-05-06T19:23:14-07:00
[INFO] Final Memory: 25M/146M
[INFO] ------------------------------------------------------------------------
|
Clone and Build JDK 9 REPL
OpenJDK codename for the project is Kulla which means “The God of Builders”. Planned name for the tool is jshell
.
- Check out the workspace:
12345678910workspaces> hg clone http://hg.openjdk.java.net/kulla/dev kullarequesting all changesadding changesetsadding manifestsadding file changesadded 1453 changesets with 2226 changes to 172 filesupdating to branch default109 files updated, 0 files merged, 0 files removed, 0 files unresolved - Get the sources:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596workspaces> cd kullakulla> chmod +x ./get_source.shkulla> ./get_source.sh# Repositories: corba jaxp jaxws langtools jdk hotspot nashorncorba: hg clone http://hg.openjdk.java.net/kulla/dev/corba corbajaxp: hg clone http://hg.openjdk.java.net/kulla/dev/jaxp jaxpcorba: requesting all changesjaxp: requesting all changescorba: adding changesetsjaxp: adding changesetscorba: adding manifestsjaxp: adding manifestscorba: adding file changesjaxp: adding file changescorba: added 669 changesets with 4913 changes to 2576 filescorba: updating to branch defaultcorba: 1184 files updated, 0 files merged, 0 files removed, 0 files unresolvedjaxws: hg clone http://hg.openjdk.java.net/kulla/dev/jaxws jaxwsjaxws: requesting all changesjaxws: adding changesetsjaxws: adding manifestsjaxws: adding file changesjaxp: added 728 changesets with 10192 changes to 7393 filesjaxp: updating to branch defaultjaxp: 3044 files updated, 0 files merged, 0 files removed, 0 files unresolvedlangtools: hg clone http://hg.openjdk.java.net/kulla/dev/langtools langtoolslangtools: requesting all changeslangtools: adding changesetslangtools: adding manifestsjaxws: added 589 changesets with 20521 changes to 10746 filesjaxws: updating to branch defaultjaxws: 3750 files updated, 0 files merged, 0 files removed, 0 files unresolvedjdk: hg clone http://hg.openjdk.java.net/kulla/dev/jdk jdklangtools: adding file changesjdk: requesting all changesjdk: adding changesetsjdk: adding manifestslangtools: added 3173 changesets with 28112 changes to 9103 fileslangtools: updating to branch defaultlangtools: 7100 files updated, 0 files merged, 0 files removed, 0 files unresolvedhotspot: hg clone http://hg.openjdk.java.net/kulla/dev/hotspot hotspothotspot: requesting all changeshotspot: adding changesetshotspot: adding manifestshotspot: adding file changeshotspot: added 8073 changesets with 45889 changes to 6290 fileshotspot: updating to branch defaulthotspot: 5030 files updated, 0 files merged, 0 files removed, 0 files unresolvednashorn: hg clone http://hg.openjdk.java.net/kulla/dev/nashorn nashornnashorn: requesting all changesnashorn: adding changesetsnashorn: adding manifestsjdk: adding file changesnashorn: adding file changesnashorn: added 1252 changesets with 11596 changes to 3595 filesnashorn: updating to branch defaultnashorn: 2867 files updated, 0 files merged, 0 files removed, 0 files unresolvedjdk: added 11805 changesets with 116593 changes to 42135 filesjdk: updating to branch defaultjdk: 23192 files updated, 0 files merged, 0 files removed, 0 files unresolved# Repositories: . corba jaxp jaxws langtools jdk hotspot nashorn.: cd . && hg pull -ucorba: cd corba && hg pull -ujaxp: cd jaxp && hg pull -ujaxws: cd jaxws && hg pull -ulangtools: cd langtools && hg pull -ujdk: cd jdk && hg pull -uhotspot: cd hotspot && hg pull -unashorn: cd nashorn && hg pull -ujaxws: pulling from http://hg.openjdk.java.net/kulla/dev/jaxwscorba: pulling from http://hg.openjdk.java.net/kulla/dev/corbalangtools: pulling from http://hg.openjdk.java.net/kulla/dev/langtoolshotspot: pulling from http://hg.openjdk.java.net/kulla/dev/hotspotjdk: pulling from http://hg.openjdk.java.net/kulla/dev/jdk.: pulling from http://hg.openjdk.java.net/kulla/devjaxp: pulling from http://hg.openjdk.java.net/kulla/dev/jaxpnashorn: pulling from http://hg.openjdk.java.net/kulla/dev/nashornnashorn: searching for changesnashorn: no changes foundjaxws: searching for changesjaxws: no changes foundjaxp: searching for changesjaxp: no changes foundcorba: searching for changescorba: no changes foundjdk: searching for changeshotspot: searching for changeshotspot: no changes foundjdk: no changes found.: searching for changes.: no changes foundlangtools: searching for changeslangtools: no changes found - Edit
langtools/repl/scripts/compile.sh
script such that it looks like:
123456#!/bin/shJLINE2LIB=/Users/arungupta/workspaces/jline2/target/jline-2.13-SNAPSHOT.jarmkdir -p buildjavac -Xlint:unchecked -Xdiags:verbose -cp ${JLINE2LIB} -d build ../src/jdk.jshell/share/classes/*/*/*.java ../src/jdk.jshell/share/classes/*/*/*/*/*.java ../src/jdk.jshell/share/classes/*/*/*/*/*/*.java#!/bin/sh
for OSX and addingJLINE2LIB
to the location of your previously compiledjline2
workspace.javac
is picked from JAVA_HOME that is referring to JDK 9. - Compile the REPL tool by invoking the script from
langtools/repl
directory:
1234repl> chmod +x ./scripts/compile.shrepl> ./scripts/compile.sh
Run JDK 9 REPL
- Edit
langtools/repl/scripts/run.sh
script such that it looks like:
12345#!/bin/shJLINE2LIB=/Users/arungupta/workspaces/jline2/target/jline-2.13-SNAPSHOT.jarjava -ea -esa -cp build:${JLINE2LIB} jdk.internal.jshell.tool.JShellTool "$@"!/bin/sh
for OSX and addingJLINE2LIB
. - Run REPL as:
12345repl> ./scripts/run.sh| Welcome to JShell -- Version 0.428| Type /help for help
JDK 9 REPL Hello World
Unlike the introduction of bouncing ball or dancing Duke that was used to introduce Java, we’ll just use the conventional Hello World for REPL
Run “Hello World” as:
1
2
3
4
|
-> System.out.println("Hello World");
Hello World
|
Voila!
No public static void main
, no class creation, no ceremony, just clean and simple Java code. The entered text is called as “snippet”.
The complete Java code can be seen using /list all
and looks like:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
-> /list all
1 : import java.util.*;
2 : import java.io.*;
3 : import java.math.*;
4 : import java.net.*;
5 : import java.util.concurrent.*;
6 : import java.util.prefs.*;
7 : import java.util.regex.*;
8 : void printf(String format, Object... args) { System.out.printf(format, args); }
9 : System.out.println("Hello World");
|
This snippet can be saved to a file as:
1
2
3
|
-> /save test
|
Note this is not a Java file. Saved snippet is exactly what was entered:
1
2
3
4
|
repl> more test
System.out.println("Hello World");
|
And the tool can be exited as:
1
2
3
4
|
-> /exit
| Goodbye
|
Or you can just hit Ctrl+C.
Complete list of commands can be easily seen:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
-> /help
Type a Java language expression, statement, or declaration.
Or type one of the following commands:
/l or /list [all] -- list the source you have typed
/seteditor <executable> -- set the external editor command to use
/e or /edit <name or id> -- edit a source entry referenced by name or id
/- or /drop <name or id> -- delete a source entry referenced by name or id
/s or /save [all|history] <file> -- save the source you have typed
/o or /open <file> -- open a file as source input
/v or /vars -- list the declared variables and their values
/m or /methods -- list the declared methods and their signatures
/c or /classes -- list the declared classes
/x or /exit -- exit the REPL
/r or /reset -- reset everything in the REPL
/f or /feedback <level> -- feedback information: off, concise, normal, verbose, default, or ?
/p or /prompt -- toggle display of a prompt
/cp or /classpath <path> -- add a path to the classpath
/h or /history -- history of what you have typed
/setstart <file> -- read file and set as the new start-up definitions
/savestart <file> -- save the default start-up definitions to the file
/? or /help -- this help message
Supported shortcuts include:
<tab> -- show possible completions for the current text
Shift-<tab> -- for current method or constructor invocation, show a synopsis of the method/constructor
|
JDK 9 REPL Next Steps and Feedback
Follow the REPL Tutorial to learn more about the tool’s capability. Here is a quick overview:
- Accepts Java statements, variable, method, and class definitions, imports, and expressions
- Commands for settings and to display information, such as
/list
to display the list of snippets,/vars
to display the list of variables,/save
to save your snippets,/open
to read them back in. - History of snippets is available, snippets can be edited by number, and much more
Here is an RFE that would be useful:
- Export a snippet as full blown Java class
A subsequent blog will showcase how this could be used for playing with a Java EE application. How would you use REPL?
Discuss the project/issues on kulla-dev.
Enjoy!
Wow, this is great
Started using REPL. How are these code windows created ?
Do you mean in the blog? These are wordpress plugins. Or something else?
hi arun,
am interacting with you again after a while (after you transition to oracle and then to REDHAT).
I have a windows box. Now, how do I build kulla on windows ? Isn’t there a getsources.bat file ?
thank you,
BR,
~A
hi arun,
now that I got hold of kulla.jar from (https://goo.gl/IqBP2i). Now, how/where do I deploy kulla.jar and the jline2 to get my REPL going ?
thank you,
Looks like jline was merged into the kulla project on July 7.
http://hg.openjdk.java.net/kulla/dev/rev/dd33ad17d6fa
This causes the compile to break.
What worked for me was using compile.sh that comes with kulla and make a couple adjustments …
1: On a mac …
Use #!/bin/sh
2: Set the JDK_REPO_ROOT to point to the right location
JDK_REPO_ROOT=/Users/alexryan/projects/jshell/kulla/jdk
Alex,
Thanks, yes the script has updated and the blog needs a refresh as well.
You can also use docker to experiment with the repl:
docker run -it java:9 jshell
Lovely, that worked like a charm:
docker run -it java:9 jshell
Unable to find image ‘java:9’ locally
9: Pulling from library/java
fd8abc45a665: Pull complete
6b9443a233f0: Pull complete
0335de578c48: Pull complete
cba95d080490: Pull complete
626da3191cff: Pull complete
e3359378c8f8: Pull complete
82896c1f6dcb: Pull complete
1cfe40c802a8: Pull complete
b2dea43f58ba: Pull complete
680dba759456: Pull complete
b2a90556d549: Pull complete
d7b4897e4bdf: Pull complete
Digest: sha256:c971300628da39afa6df3dcafd9d88f90d85530d1f4e763a010dbd7524edce20
Status: Downloaded newer image for java:9
Dec 16, 2015 6:37:36 PM java.util.prefs.FileSystemPreferences$1 run
INFO: Created user preferences directory.
| Welcome to JShell — Version 1.9.0-internal
| Type /help for help