5min read

Exploring Java 9: The JShell

Java 9 had its delays but it’s finally coming (there is even a counter showing when)! It’s going to bring us some cool stuff that has never been there, namely: Modules, HTTP 2.0 support, improvements in Processing API, G1 Garbage Collector as the default one… We could go on and on, because there are lots of JEPs included (the full list is available here) so let’s just focus on one neat and helpful tool that Java 9 release will bring us - the JShell.

A language shell

Let’s say you are prototyping. Or you want to learn something. Or teach someone. You probably want to know (see) what exactly happens after each line of an entered code. You don’t want to focus on setting up the project, creating .java file, writing your main class and the main method, compiling, running… it’s cumbersome and I already feel discouraged!

For such cases we need something that gives us quick feedback, leaving unimportant stuff behind. And that’s what REPLs are for. They:

  • Read the code you enter,
  • Evaluate it,
  • Print the result,
  • Do it on and on until you tell them to stop (L stands for Loop).

Java creators decided to introduce a REPL in the ninth version. It’s called JShell and I’ll try to show you how easy this tool is and what power it has.

The JShell:

JShell, aka project Kulla, comes with JDK9 - you don’t need to install anything else. Run it by typing “jshell” in the console. It will greet you with nice, welcoming message:

lukasz@MacBook ~> jshell
|  Welcome to JShell -- Version 9-ea
|  For an introduction type: /help intro

Nothing can stop me from writing a code snippet now:

jshell> "Hello "
$1 ==> "Hello "
jshell> $1.
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> $1.concat("there!")
$2 ==> "Hello there!"


Three things to notice here. First, JShell puts the result of the evaluated code into variables so that I could use it later. Second, I somehow made it to show us all possible methods I can invoke on the variables type (it was the Tab button, no surprise here). Third - there was no semicolon. This has been taken away from us in JShell to make our work more convenient.

Actually, there is one more thing that we do not have to worry about while coding in JShell. The checked exceptions:

//no “try” here
jshell> Thread.sleep(1000)
// (no “catch (InterrupedException ex”) here either


Another useful thing we can do in JShell is using yet undeclared code:

jshell> void foo() {
   ...> System.out.println("Foo");
   ...> bar();
   ...> }
|  created method foo(), however, it cannot be invoked until method bar() is declared

jshell> void bar() {
   ...> System.out.println("Bar");
   ...> }
|  created method bar()

jshell> foo()


As you can see, JShell has agreed to using the bar() method. It displayed a message informing that I should declare the method before invoking code that uses it. Also - an important thing to notice: here I had to put semicolons in methods (the same goes with try/catch blocks for checked exceptions). In fact, this seems to be a good thing in methods.
It’s nice that I can just copy and paste them from JShell to the program I’m working on, isn’t it?

So far, so good, but we probably might want to check, what is going on with my JShell session. There are appropriate commands to do that too (/vars, /methods, /types, /imports):

jshell> /vars
|    String $1 = "Hello"
|    String $2 = "Hello there!"

jshell> /methods
|    foo ()void
|    bar ()void

jshell> /types
|    interface Baz
|    class BazImpl

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

jshell> /m
|    foo ()void
|    bar ()void


Yet another coding booster: if there is no ambiguity, we don’t have to write the whole command name.

What if we would like to edit something? On top redefining variables, methods and types, dropping them (/drop) and writing again, there is yet another interesting tool. The /edit command. By using it, we can write whatever code we like in a simple text editor and hit accept. This can become very handy while putting a long text to a variable, like this:


Last but not least - there are shortcuts. I already mentioned the “Tab” completion but JShell creators didn’t stop there. “Shift + Tab” allows us to see what constructors or methods are there to use. Pressing it twice opens the Javadoc.

jshell> new String( //press the combination here
String(String original)
String(char[] value)
String(char[] value, int offset, int count)
String(StringBuilder builder)
<press shift-tab again to see javadoc>

Initializes a newly created String object so that it represents an empty character
sequence.Note that use of this constructor is unnecessary since Strings are immutable.
<press space for next javadoc, Q to quit>

JShell can also infer types while declaring things. Simply press ”fn + esc + v” (shortcut for Mac OS - may differ on other platforms) at the end of a variable you’re creating. JShell will automatically tell you what the type is. Now all you need to do is to name the variable:

jshell> new String("Infer my type") //press the combination here
jshell> String <put the name here> = new String("Infer my type")


We need fine and intuitive tools and JShell is certainly one of them. It’s easy to learn, has a lot of handy features and it’s not too big. If you’re still curious, simply enter the /help command and check it out yourself! For me it was a pleasure and that makes it yet another good reason to look forward to Java9. Stay tuned for more!

jshell> /exit
|  Goodbye
lukasz@MacBook ~>


ŁukaszSenior Software Engineer


Sign in and expect sharp insights, recommendations, ebooks and fascinating project stories delivered to your inbox

The controller of the personal data that you are about to provide in the above form will be Polidea sp. z o.o. with its registered office in Warsaw at ul. Przeskok 2, 00-032 Warsaw, KRS number: 0000330954, tel.: 0048 795 536 436, email: (“Polidea”). We will process your personal data based on our legitimate interest and/or your consent. Providing your personal data is not obligatory, but necessary for Polidea to respond to you in relation to your question and/or request. If you gave us consent to call you on the telephone, you may revoke the consent at any time by contacting Polidea via telephone or email. You can find detailed information about the processing of your personal data in relation to the above contact form, including your rights relating to the processing, HERE.

Data controller:

The controller of your personal data is Polidea sp. z o.o. with its registered office in Warsaw at ul. Przeskok 2, 00-032 Warsaw, KRS number: 0000330954, tel.: [0048795536436], email: [] (“Polidea”)

Purpose and legal bases for processing:


Used abbreviations:

GDPR – Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016
on the protection of natural persons with regard to the processing of personal data and on the free movement
of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)

ARES – Polish Act on Rendering Electronic Services dated 18 July 2002

TL – Polish Telecommunications Law dated 16 July 2004

1)        sending to the given email address a newsletter including information on Polidea’s new projects, products, services, organised events and/or general insights from the mobile app business world |art. 6.1 a) GDPR, art. 10.2 ARES and art. 172.1 TL (upon your consent)

Personal data:name, email address

2)       statistical, analytical and reporting purposes |art. 6. 1 f) GDPR (based on legitimate interests pursued by Polidea, consisting in analysing the way our services are used and adjusting them to our clients’ needs, as well as developing new services)

Personal data:name, email address

Withdrawal of consent:

You may withdraw your consent to process your personal data at any time.

Withdrawal of the consent is possible solely in the scope of processing performed based on the consent. Polidea is authorised to process your personal data after you withdraw your consent if it has another legal basis for the processing, for the purposes covered by that legal basis.

Categories of recipients:

Your personal data may be shared with:

1)       authorised employees and/or contractors of Polidea

2)       persons or entities providing particular services to Polidea (accounting, legal, IT, marketing and advertising services) – in the scope required for those persons or entities to provide those services to Polidea


Retention period:

1)       For the purpose of sending newsletter to the given email address – for as long as the relevant consent is not withdrawn

2)       For statistical, analytical and reporting purposes – for as long as the relevant consent is not withdrawn

Your rights:


Used abbreviation:

GDPR – Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016
on the protection of natural persons with regard to the processing of personal data and on the free movement
of such data, and repealing Directive 95/46/EC (General Data Protection Regulation)

According to GDPR, you have the following rights relating to the processing of your personal data, exercised by contacting Polidea via [e-mail, phone].

1)       to access to your personal data (art. 15 GDPR) by requesting sharing and/or sending a copy of all your personal data processed by Polidea

2)       to request rectification of inaccurate personal data
(art. 16 GDPR) by indicating the data requiring rectification

3)       to request erasure of your persona data (art. 17 GDPR); Polidea has the rights to refuse erasing the personal data in specific circumstances provided by law

4)       to request restriction of processing of your personal data (art. 18 GDPR) by indicating the data which should be restricted

5)       to move your personal data (art. 20 GDPR) by requesting preparation and transfer by Polidea of the personal data that you provided to Polidea to you or another controller in a structured, commonly used machine-readable format

6)       to object to processing your personal data conducted based on art. 6.1 e) or f) GDPR, on grounds relating to your particular situation (art. 21 GDPR)

7)       to lodge a complaint with a supervisory authority,
in particular in the EU member state of your habitual residence, place of work or place of the alleged infringement if you consider that the processing
of personal data relating to you infringes the GDPR
(art. 77.1 GDPR)

No obligation to provide data:

Providing your personal data is not obligatory, but necessary for Polidea to provide you the newsletter service

Refusal to provide the above data will result in inability to receive the newsletter service.


In the process of providing the newsletter service, we make decisions in an automated way, including profiling, based on the data you provide.


“Profiling” means automated processing of personal data consisting of the use of your personal data to evaluate certain personal aspects relating to you, in particular to analyze or predict aspects concerning your personal preferences and interests.


The automated decisions are taken based on the analysis of clicked and viewed content. They affect the targeting of specific newsletter content to selected users registered to receive the newsletter service, based on the anticipated interests of the recipient.