Introduction

What is JShell

The JShell tool is a command line tool that facilitates exploratory programming by providing interactive use of Java Programming Language elements. JShell is a REPL (Read-Evaluate-Print-Loop). It is ideal both for learning the Java language and exploring unfamiliar code (include new Java APIs). Typical Java development means writing a complete program, then compiling it (fixing any errors), the running it, figuring out what is wrong, editing, and repeating. With JShell you can enter program elements one at a time, immediately seeing the result and adjusting accordingly. During development, code can be pasted into JShell, and/or working code pasted from JShell into a program editor.

Starting JShell

First install JDK 9. JShell is included in JDK 9. To launch the JShell tool, just type jshell at the command-line:

% jshell

Throughout this tutorial, bold fixed-width font will be used to indicate text that you type as you follow along.

If you did enter the JShell tool, type /exit to leave:

% jshell
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

jshell> /exit
|  Goodbye

For this tutorial all examples use verbose mode. So that what you see matches, I recommend following along in verbose mode. Once you are familiar, you will probably want to run in normal or a more concise mode. To start JShell in verbose mode type:

% jshell -v

Snippets

Trying it out

JShell accepts Java statements, variable, method, and class definitions, imports, and expressions. I'll refer to these pieces of Java code as snippets. For example, you can enter a statement at the prompt, any side-effects will take place and any output displayed:

jshell> System.out.println("Hi");
Hi
                                                                                   
jshell>

By default, JShell will give you information about what you entered. Here, a variable is defined:

jshell> int x = 45
x ==> 45
|  created variable x : int

First, the result is shown, this can be read: the variable x has the value 45. Since we are in verbose mode, there is also a description of what occurred, informative messages start with a vertical bar. Note: both the name and type of the created variable are shown.

Note that terminating semicolons will be automatically added to the end of your snippet if missing.

When an expression is entered that doesn't have a named variable, a scratch variable is created so that the value can be referenced later :

jshell> 2 + 2
$3 ==> 4
|  created scratch variable $3 : int

jshell> String twice(String s) {
   ...>    return s + s;
   ...> }
|  created method twice(String)

jshell> twice("Ocean")
$5 ==> "OceanOcean"
|  created scratch variable $5 : String

Changing Definitions

To change the definition of a variable, method, or class you have previously entered, simply enter a new definition. For example, the method we defined above can get new new definition:

jshell> String twice(String s) {
   ...>     return "Twice:" + s;
   ...> }
|  modified method twice(String)

jshell> twice("thing")
$7 ==> "Twice:thing"
|  created scratch variable $7 : String

Note that rather than saying "created method", as before, it says "modified method" -- this means that the definition was changed, but has the same signature, and thus all existing usages continue to be valid.

You may also change definitions in incompatible ways. For example:

jshell> String x
x ==> null
|  replaced variable x : String
|    update overwrote variable x : int

We have changed the type of the variable x, note that it now says "replaced". More on this later.

We started JShell in the verbose feedback mode, so it is quite chatty. You can set the amount and format of output with the /set feedback command, for example /set feedback concise. If you plan to primarily use JShell by pasting from other windows, you may wish to use a feedback mode with no prompt and only error feedback: /set feedback silent.

Forward Reference

Because a goal of JShell is to support exploratory programming (and because some forms of programming require it), JShell allows you to define methods whose bodies reference methods, variables, or classes which are not yet defined. Let's say you wish to define a method for the volume of a sphere, you can enter the formula:

jshell> double volume(double radius) {
   ...>     return 4.0 / 3.0 * PI * cube(radius);
   ...> }
|  created method volume(double), however, it cannot be invoked until variable PI, and method cube(double) are declared

JShell allows the definition but warns of what is yet to be defined. The definition may be referenced, but if execution is attempted, it will fail:

jshell> double PI = 3.1415926535
PI ==> 3.1415926535
|  created variable PI : double

jshell> volume(2)
|  attempted to call method volume(double) which cannot be invoked until method cube(double) is declared

jshell> double cube(double x) { return x * x * x; }
|  created method cube(double)
|    update modified method volume(double)

jshell> volume(2)
$5 ==> 33.510321637333334
|  created scratch variable $5 : double

With all definitions in place, volume now works.

I'll use this code to illustrate more about incompatible replacement. Let's say you aren't happy with the precision of PI:

jshell> BigDecimal PI = new BigDecimal("3.141592653589793238462643383")
PI ==> 3.141592653589793238462643383
|  replaced variable PI : BigDecimal
|    update modified method volume(double) which cannot be invoked until this error is corrected: 
|      bad operand types for binary operator '*'
|        first type:  double
|        second type: java.math.BigDecimal
|          return 4.0 / 3.0 * PI * cube(radius);
|                 ^------------^
|    update overwrote variable PI : double

The new definition of PI is type incompatible with the definition of volume(). Because we are in verbose mode, update information is shown for other definitions affected by the change -- here describing the incompatibility. Note that verbose mode is the only built-in feedback mode which will display update information. In other feedback modes no warning will be displayed until the code is executed -- this is to prevent flurries of uninteresting updates. In all cases, executed the volume() method will display the issue:

jshell> volume(2)
|  attempted to call method volume(double) which cannot be invoked until this error is corrected: 
|      bad operand types for binary operator '*'
|        first type:  double
|        second type: java.math.BigDecimal
|          return 4.0 / 3.0 * PI * cube(radius);
|                 ^------------^

Exceptions

In an exception back-trace, a location within REPL entered code is displayed as the #id/linenumber, where snippet id is the number displayed in /list and line-number is the line-number within the snippet. So, below, the exception occurs in snippet #1 aka divide() on the second line of divide:

jshell> int divide(int x, int y) {
   ...>     return x / y;
   ...> }
|  created method divide(int,int)

jshell> divide(5, 0)
|  java.lang.ArithmeticException thrown: / by zero
|        at divide (#1:2)
|        at (#2:1)
                             
jshell> /list
                                                            
   1 : int divide(int x, int y) {
           return x / y;
       }                                                                                                                                                                
   2 : divide(5, 0)

Tab Completion -- Snippets

Press the tab key to complete the current entry. For example:

jshell> vol<tab>

Will be replaced with:

jshell> volume(

If there is more than one completion the set of completions will be listed:

jshell> System.c<tab>
class                 clearProperty(        console()             currentTimeMillis()   

jshell> System.c

Any common characters will be added and the cursor will placed at the end of input, so that more can be added.

When you are at a method call's open-parenthesis, tab will show completions as above (if there is anything interesting to show), and will show the parameter types:

jshell> "hello".startsWith(<tab>
Signatures:
boolean String.startsWith(String prefix, int toffset)
boolean String.startsWith(String prefix)

<press tab again to see documentation>

jshell> "hello".startsWith(

Pressing tab again will show a plain-text version of documentation of the first method.

jshell> "hello".startsWith(<tab>
boolean String.startsWith(String prefix, int toffset)
Tests if the substring of this string beginning at the specified index starts with the
specified prefix.

Parameters:
prefix - the prefix.
toffset - where to begin looking in this string.

Returns:
true if the character sequence represented by the argument is a prefix of the substring of this
          object starting at index toffset ; false otherwise. The result is false if toffset is
          negative or greater than the length of this String object; otherwise the result is
          the same as the result of the expression
                    this.substring(toffset).startsWith(prefix)
                    

<press tab to see next documentation>

jshell> "hello".startsWith(

Snippet Transformation

When entering an identifier which needs to be imported, press <shift-tab>i (that is, hold down shift while pressing tab, then release and press i) and a menu will appear allowing you to automatically add the import:

jshell> new JFrame<shift-tab>i
0: Do nothing
1: import: javax.swing.JFrame
Choice: 1
Imported: javax.swing.JFrame

jshell> new JFrame

Note: there may be more than one choice of import.

After entering an expression, you can convert the expression to a variable declaration with <shift-tab>v. That is, the expression will become the initializer of the variable declaration and type of the variable will be the type of the expression:

jshell> new JFrame("Demo")<shift-tab>v
jshell> JFrame | = new JFrame("Demo")

The cursor will be positioned at the location where the variable name should go. Type the variable name and press return

Note: the expression must be valid or the transformation request will be ignored. Thus, the import of JFrame was required before the variable transformation.

Sometimes the result type of the expression has not been imported. In that case <shift-tab>v will offer to both import and create the variable. We continue, from above, by entering the variable name 'frame' and pressing return:

jshell> JFrame frame = new JFrame("Demo")
frame ==> javax.swing.JFrame[frame0,0,0,0x0,invalid,hidden, ... tPaneCheckingEnabled=true]
|  created variable frame : JFrame

jshell> frame.setSize(300, 200)

jshell> frame.setVisible(true)

jshell> frame.getGraphics()<shift-tab>v
0: Do nothing
1: Create variable
2: import: java.awt.Graphics. Create variable
Choice: 2
Imported: java.awt.Graphics

jshell> Graphics | = frame.getGraphics()

The name of the graphics context variable should be entered.

Commands

Commands -- Introduction

JShell has a number of commands for controlling the environment and displaying information. They are distinguished from snippets by a leading slash. You can get information on the current variables, methods, and types with the /vars, /methods, and /types commands. You can get a list of entered snippets with the /list command. For example:

jshell> /vars
|    int x = 45
|    int $3 = 4
|    String $5 = "OceanOcean"

jshell> /methods
|    twice (String)String

jshell> /list

   1 : System.out.println("Hi");
   2 : int x = 45;
   3 : 2 + 2
   4 : String twice(String s) {
         return s + s;
       }
   5 : twice("Ocean")

You will note that the types and values of variables, and the type signature of methods are displayed.

JShell has start-up entries that are silently and automatically executed before JShell starts, so that you can get to work quickly. These aren't listed unless you request to see them with /list -start or /list -all:

jshell> /list -all

  s1 : import java.util.*;
  s2 : import java.io.*;
  s3 : import java.math.*;
  s4 : import java.net.*;
  s5 : import java.util.concurrent.*;
  s6 : import java.util.prefs.*;
  s7 : import java.util.regex.*;
   1 : System.out.println("Hi");
   2 : int x = 45;
   3 : 2 + 2
   4 : String twice(String s) {
         return s + s;
       }
   5 : twice("Ocean")

The default start-up entries are several common imports. You can personalize your start-up entries with the /set start command; For information on this, type: /help /set start. The /save -start command is useful if you wish to create your file as a variant to the default start-up.

Use /help for a list of commands.

Other important commands include /exit to leave JShell, /save to save your snippets, and /open to read them back in.

Tab Completion -- Commands

Tab completion works for commands and command arguments as well:

jshell> /<tab>
/!          /?          /drop       /edit       /env        /exit       /help
/history    /imports    /list       /methods    /open       /reload     /reset      
/save       /set        /types      /vars       

<press tab again to see synopsis>

jshell> /

Unique completions are done in-place:

jshell> /l<tab>

is replaced with:

jshell> /list

Tab completion works for command options:

jshell> /list -<tab>
-all       -history   -start     

<press tab again to see synopsis>

jshell> /list -

Note the message that another tab will show the command synopsis, the synopsis is a short description of the command. Tab again will show the /help documentation:

jshell> /list -<tab>
list the source you have typed

<press tab again to see full documentation>

jshell> /list -<tab>
Show the source of snippets, prefaced with the snippet id.

/list
    List the currently active snippets of code that you typed or read with /open

/list -start
    List the automatically evaluated start-up snippets

/list -all
    List all snippets including failed, overwritten, dropped, and start-up

/list <name>
    List snippets with the specified name (preference for active snippets)

/list <id>
    List the snippet with the specified snippet id

jshell> /list -<tab>

Unique argument completions are done in-place:

jshell> /list -a<tab>

is replaced with:

jshell> /list -all

Snippet names can also be tab completed:

jshell> /ed v<tab>

is replaced with:

jshell> /ed volume

Using tab in a file argument position of the command shows the available files:

jshell> /open <tab>
myfile1      myfile2    definitions.jsh

<press tab again to see synopsis>

jshell> /open 

Unique file name completions are done in-place:

jshell> /open d<tab>

is replaced with:

jshell> /open definitions.jsh

Command Abbreviation

Commands, /set sub-commands, command arguments, and command options can all be abbreviated, as long as they are unique.

Since, /list is the only command that begins with /l and the only /list command option that begins with -a is -all:

jshell> /list -all

can be abbreviated:

jshell> /l -a

And, /set is the only command that begins with /se, the only /set sub-command that begins with fe is feedback, and, unless user modes are added, verbose is the only feedback mode that begins with v. the command:

jshell> /set feedback verbose 

can be abbreviated:

jshell> /se fe v

Note that /s is not sufficient as /save has the same beginning. When in doubt you can use tab completion.

Editors

To more easily edit past entries, particularly one's of many lines, you can invoke an editor on the snippet by providing its name or id (number in /list):

jshell> /edit volume

Or, for all snippets and to enter new ones, /edit without an argument. When you save in the editor, any snippet that is changed or new will be entered, you will see the feedback from the snippets in JShell window however there will be no JShell prompt and you cannot enter commands or snippets in JShell window until the editor is closed.

If you do not specify an editor, a simple built-in editor will be provided. Specify the editor to invoke with the /set editor command. The argument to the command is the external editor you wish to use. This editor must open its own window. For example:

jshell> /set editor kwrite
|  Editor set to: kwrite

jshell> /edit ...

user defines x in the external editor window and selects save

|  created variable x of type int with initial value 6

user closes the external editor

jshell> 

Shell Editing

User input editing is built on JLine2 which is functionally similar to BSD editline and GNU readline in Emacs mode. It can be used to edit the current line or access the whole history reaching back through many sessions of jshell tool use.

This tutorial will use "Ctrl-x" to mean hold down the Control key and then press the x key; And "Meta-x" to mean hold down the Meta key (often the left Alt key) and then press the x key.

Basic navigation within a line uses the right/left arrow keys or alternatively Ctrl-b and Ctrl-f (for backwards and forwards). Navigation between lines in the history uses the up/down arrow keys. So, pressing up-arrow once replaces the current line with the previous command or snippet line. Pressing up-arrow again brings you to the line previous to that. The history contains both commands and snippet lines -- note that snippets may have multiple lines, up/down-arrow will navigate through individual lines of a snippet.

Movement Commands
Key Action
Return Enter the current line
Left-arrow Move backward one character
Right-arrow Move forward one character
Up-arrow Move up one line (backward through history)
Down-arrow Move down one line (forward through history)
Ctrl-a Move to the beginning of the line
Ctrl-e Move to the end of the line
Meta-b Move backward a word
Meta-f Move forward a word

History Navigation

JShell maintains a history of snippets and commands. You navigate this history to re-enter or edit prior input with the up/down/left/right arrows. Entered text will be inserted. The Delete key can be used to delete text. Press the Enter key to accept the history line again (modified or not).

You can move a snippet at a time by using control-up and control-down (that is holding the control key while pressing the up or down key).

For example:

jshell> class C {                                                                                                                                                       
   ...>   int x;                                                                                                                                                        
   ...> }                                                                                                                                                               
|  created class C                                                                                                                                                      
                                                                                                                                                                        
jshell> /list                                                                                                                                                           
                                                                                                                                                                        
   1 : class C {                                                                                                                                                        
         int x;                                                                                                                                                         
       }                                                                                                                                                                
                                                                                                                                                                    
jshell> <up-arrow>

The up-arrow key will cause the line to show:

jshell> /list                                                                                                                                                           

Pressing up-arrow again will show:

jshell> }

the last line of the class definition. Pressing the down-arrow will return to the /list command, and pressing return will execute it:

jshell> /list                                                                                                                                                           
                                                                                                                                                                        
   1 : class C {                                                                                                                                                        
         int x;                                                                                                                                                         
       }                                                                                                                                                                

Ctrl-up-arrow will go up by snippets. So, for single-line snippets Ctrl-up-arrow behaves like up-arrow. But, for multi-line snippets, like class C, it will do the top of the snippet.

Modifying

Text can be added at the current cursor position simply by typing it. The Delete key will delete a character to the right of the cursor, the Backspace key will delete to the left.

Deletion Commands
Key Action
Delete Delete character under the cursor
Backspace Delete character before the cursor
Ctrl-k Kill (delete) the text from the cursor to the end of the line
Meta-d Kill from the cursor to the end of the word
Ctrl-w Kill from the cursor to the previous whitespace
Ctrl-y Yank (paste) the most recently killed text into the line
Meta-y After Ctrl-y, press to cycle through previously killed text

Search and More

Search through history is a powerful tool. Press Ctrl-r followed by a string you wish to search for in your history. The search will proceed backward, starting from you most recent entrees and include previous sessions of the jshell tool. Assuming the previous example, pressing Ctrl-r at the prompt:

jshell> <Ctrl-r>

will replace the prompt with:

(reverse-i-search)`': 

Typing "class" will change the display to:

(reverse-i-search)`class': class C {

Showing the most recent line with the text "class". The search is incremental, so this line is retrieved with just the first character "c". You can continue to search earlier in the history with by pressing Ctrl-r repeatedly. Ctrl-s will move the search back towards the present.

You can define a keyboard-macro using Ctrl-x followed by an open-parenthesis "Ctrl-x (" then entering your text, finally typing "Ctrl-x )". When you wish to use your macro type "Ctrl-x e".

Miscellaneous Commands
Key Action
Ctrl-r Search backward through history
Ctrl-s Search forward through history
Ctrl-x ( Start entering macro
Ctrl-x ) Finish macro
Ctrl-x e Use macro

For more information see the JLine2 user information and the GNU Readline documentation.

Working with External Code

Setting a Classpath

One way you can connect external code to be accessed by the jshell tool is setting the classpath. The classpath can be set on the command-line:

 % jshell --class-path myOwnClassPath

Your classpath should point to directories or JAR files with the packages you wish to access. The code must be compiled into class files. Code in the default package (also known as the unnamed package) cannot be accessed from JShell. Once you have set the classpath these packages can be imported:

jshell> import my.cool.code.*

You also use the '/env' command to set the classpath:

jshell> /env --class-path myOwnClassPath
|  Setting new options and restoring state.

Note that this command resets the execution state, reloading any current snippets with the new classpath setting (or other environment setting).

Setting Module Options

Similiarly, the module path may be set, additional modules to resolve specified, and module exports given -- on either the jshell tool command-line or in options to /env:

 % jshell --module-path myOwnModulePath  --add-modules my.module

To see current environment settings, use '/env' without arguments:

 jshell> /env
 |     --add-modules my.module
 |     --module-path myOwnModulePath
 |     --class-path myOwnClassPath

For details see:

jshell> /help context

Feedback Modes

Setting a Feedback Mode

A feedback mode is a named user interaction configuration. There are built-in modes and the user can create custom modes. The built-in modes cannot be modified, but a copy can be made as the base of a user defined mode. There four built-in modes, in descending order of verbosity: verbose, normal, concise, and silent. This table sketches the differences:

Mode Value snippets Declaration Updates Commands Prompt
verbose name ==> value (and description) Yes Yes Yes \njshell>
normal name ==> value Yes No Yes \njshell>
concise name ==> value (only expressions) No No No jshell>
silent No No No No ->

Where "Value snippets" indicates what is shown for snippets that have value, like expressions, assignment, and variable declarations; "Declaration" indicates if there is feedback for declarations for methods, classes, enum, interfaces, and annotation interfaces; "Updates" indicates if changes to other than the current snippet are shown; and "Commands" indicates if commands give feedback indicating success.

Unless set by a command-line flag or the /set feedback command, the feedback mode will be "normal". The /set feedback command sets the feedback mode:

jshell> /set feedback verbose 
|  Feedback mode: verbose

jshell> 2 + 2
$1 ==> 4
|  created scratch variable $1 : int

jshell> /set feedback silent 
-> 2 + 2
-> /set feedback normal 
|  Feedback mode: normal

jshell> 2 + 2
$3 ==> 4

jshell> /set feedback concise 
jshell> 2 + 2
$4 ==> 4
jshell> 

Note that when setting to "normal" or "verbose" the command feedback lets you know that has happened, but "concise" and "silent" don't. Also note the three different forms of feedback to the expression (including none for silent).

To see the current and available feedback modes, use the /set feedback command without arguments. Note that the current mode is shown as the command that would set it:

jshell> /set feedback 
|  /set feedback verbose
|  
|  Available feedback modes:
|     concise
|     normal
|     silent
|     verbose

Defining a Feedback Mode

There are three settings for a mode: the prompts, the truncation, and the format. Let's say you wish to change the prompt. The built-in modes cannot be changed, but you can easily create a copy of an existing mode -- so that is the first step:

jshell> /set mode mine normal -command
|  Created new feedback mode: mine

The new mode "mine" is a copy of the "normal" mode, the -command option indicates the you want command feedback (the "Commands" column in the table above). If, in your mode, you don't want commands to describe the action that occurred (for example, "| Created new feedback mode: mine" above), then use -quiet instead of -command.

Like all /set commands, using the /set prompt command without setting arguments will give the current setting:

jshell> /set prompt normal
|  /set prompt normal "\njshell> " "   ...> "

The first string is the regular prompt, the second is the continuation prompt which is used if the snippet extends to multiple lines. Here we set the prompts, switch to the new mode to see it, and test it out:

jshell> /set prompt mine "\nmy mode: "  ".......: "

jshell> /set feedback mine
|  Feedback mode: mine

my mode: class C {
.......:   int x;
.......: }
|  created class C

my mode:

The prompt strings may contain '%s' which will be substituted with the next snippet id -- note that what the user enters at the prompt may not be assigned that id, for example it may be an error or command.

All settings have a duration of the current tool session (note: they are not reset with /reset). If you wish them to be the default on future sessions, use the -retain option to retain them:

my mode: /set mode mine -retain

my mode: /set feedback mine -retain
|  Feedback mode: mine

my mode: /exit 
|  Goodbye
% jshell   
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

my mode: 

When values are displayed, if they are too long they are truncated. What is "too long" is determined by the /set truncation command. Without settings, it will display the current setting, these were inherited from normal mode:

my mode: /set truncation mine 
|  /set truncation mine 80 
|  /set truncation mine 1000 expression,varvalue

my mode: String big = IntStream.range(0,1200).mapToObj(n -> "" + (char) ('a' + n % 26)).collect(Collectors.joining())
big ==> "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuv ... fghijklmnopqrstuvwxyzabcd"

The selector kinds that optionally appear after the truncation length select the conditions under which that truncation setting will be in effect. Here, the case selector, which indicates the kind of snippet whose value is displayed. See /help /set truncation for details on selectors. The setting shown above means values will be truncated to 80 characters unless the value is the value of an expression (the expression case selector) or the value of a variable, as explicitly requested by entering just the variable name (the varvalue case selector). The order is important, last one wins. Had the order been reversed, all truncations would be to 80 characters.

Let's say, in our mode, we want default truncation to be 100, and only want long values if they are explicitly requested.

my mode: /set truncation mine 100

my mode: /set truncation mine 300 varvalue

my mode: big + big
$2 ==> "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi ... yzabcdefghijklmnopqrstuvwxyzabcd"

my mode: big
big ==> "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu
vwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl ... jklmnopq
rstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd"

my mode: /set mode mine -retain

Note: if these changes are as desired, the changes to the mode need to be retained.

Now let's change snippet output to our preferences.

my mode: import java.beans.*

my mode: Locale.CANADA.getUnicodeLocaleAttributes()
$5 ==> []

In the format, inherited from normal mode, an import doesn't give any feedback, and the type of a value is not shown. The format of snippet output is set with the /set format command. Try this, without settings, for some mode, to see the current format settings:

my mode: /set format mine

There is extensive help on this command with /help /set format. Please read this now and reference it as we go along. The primary feedback displayed is determined by the display field. Other fields can be defined to assist in defining the display field. The (non-silent) predefined modes define several, as can be in the output from the command above. These are inherited in our example mode. Here are display definitions for import:

my mode: /set format mine display "{pre}added import {name}{post}" import-added

my mode: /set format mine display "{pre}re-added import {name}{post}" import-modified,replaced

The name field is predefined as the name of the snippet.

my mode: import java.beans.*
|  re-added import java.beans.*

The pre and post fields have the prefix and postfix characters for each line of feedback output. Let's say we don't like the vertical bar prefix:

my mode: /set format mine pre ""

my mode: void m() {}
created method m()

my mode: import java.beans.*
re-added import java.beans.*

my mode: /set feedback mine 
Feedback mode: mine

Note: this affects all feedback including command feedback.

To show the type when displaying values, it will be easiest to change the result field defined by the predefined modes:

my mode: /set format mine result "{type} {name} = {value}{post}" added,modified,replaced-primary-ok

my mode: Locale.CANADA.getUnicodeLocaleAttributes()
Set<String> $11 = []

my mode: 2 + 2
int $12 = 4

We want result to be non-empty only when it is new/updated (added,modified,replaced), is on the entered snippet (primary), and does not have errors (ok).

To permanently delete a retained mode:

my mode: /set feedback verbose -retain
|  Feedback mode: verbose

jshell> /set mode mine -delete -retain

Scripts

JShell Scripts

A JShell script is a sequence of snippets and JShell commands, one per line, in a file.

A script can be created externally in an editor, or generated with one of these commands:

jshell> /save mysnippets.jsh

jshell> /save -history myhistory.jsh

jshell> /save -start mystartup.jsh

These, respectively, save to the specified script file the current active snippets, the history of all snippets and commands (valid and invalid), or the contents of the current startup script setting.

Script names can be an operating system filename (as above) or one of these predefined scripts:

Script Contents
DEFAULT The default startup if one is not set, includes commonly needed import declarations
PRINTING Defines JShell methods that redirect to the print, println, and printf methods in PrintStream
JAVASE Imports all Java SE packages, this is big and will cause a noticeable startup delay

Loading Scripts

Scripts may be loaded by listing them on the jshell tool command-line:

% jshell mysnippets.jsh

or on the /open command:

jshell> /open PRINTING

Start-up Scripts

The startup script(s) are loaded each time the jshell tool is reset; reset occurs on initial startup and with resetting commands (/reset, /reload, and /env). Unless set by the user, the default startup script (DEFAULT) is used, this defines commonly needed import declarations. Note: the Java language defines that the java.lang package in automatically imported so this does not need to be explicitly imported.

To set the startup script use /set start:

jshell> /set start mystartup.jsh

jshell> /reset
|  Resetting state.

As with all /set commands, the duration of the setting is the current session unless the -retain flag is used. Use without the -retain flag, as above, is generally only useful as a mechanism to safely test a startup script setting. Once the desired setting is found, it can be preserved with:

jshell> /set start -retain

then the set startup script will be loaded on your next invocation of the jshell tool.

Remember that the startup scripts are only loaded into the current session when the state is reset. Note: it is the contents of a file that is stored, rather than a reference to the file. The file is only read at the time the /set start command is run. Contrastingly, when predefined script names are used, they are by reference and may be updated with new releases of the JDK.

The startup script may alternatively be specified with the --startup command-line flag (note, command-line flags can be abbreviated, if unique):

% jshell --start mystartup.jsh

Early development versions of JShell defined a printf JShell method, this has been removed from the default startup to assure cut-and-paste compatibility with Java programs. However, it is very handy for experimentation to have print methods that don't need System.out. prefixing them. You can specify more than one startup script on /set start:

jshell> /set start -retain DEFAULT PRINTING

jshell> /exit
|  Goodbye

% jshell
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro

jshell> println("Hello World!")
Hello World!

This sets the startup to load both the default imports and printing definitions. The -retain flag is used to set these as the startup scripts of future sessions of the jshell tool. Try the /set start, without arguments, to see the details of the startup this defines.

To set more than one startup script on the command-line, use the --startup flag for each script:

% jshell --start DEFAULT --start PRINTING