Java : JShell with Examples

JShell (Java SE 18 & JDK 18) API Examples.
You will find code examples on most JShell methods.


Summary

The JShell evaluation state engine. This is the central class in the JShell API. A JShell instance holds the evolving compilation and execution state.

Class diagram

try (final var js = JShell.create()) {

    js.eval("int x = 2;");
    js.eval("int y = 3;");
    js.eval("int z = x * y;");

    js.variables().forEach(varSnippet -> {
        System.out.printf("source [ %s ] : value [ %s ]%n",
                varSnippet.source(), js.varValue(varSnippet));
    });
}

// Result
// ↓
//source [ int x = 2; ] : value [ 2 ]
//source [ int y = 3; ] : value [ 3 ]
//source [ int z = x * y; ] : value [ 6 ]

See also : Introduction to JShell (Java SE 18)


Methods

void addToClasspath (String path)

The specified path is added to the end of the classpath used in eval().

// --- PowerShell ---
//PS R:\java-work> cat .\aaa\Sample.java
//package aaa;
//
//public class Sample {
//
//    public int sum(int x, int y) {
//        return x + y;
//    }
//}
//
//PS R:\java-work> javac .\aaa\Sample.java
//
//PS R:\java-work> ls -Name aaa
//Sample.class
//Sample.java

try (final var js = JShell.create()) {

    final var path = Path.of("R:", "java-work");
    System.out.println(path); // R:\java-work

    js.addToClasspath(path.toString());

    js.eval("import aaa.Sample;");
    js.eval("var sample = new Sample();");
    js.eval("var a = sample.sum(2, 3);");

    js.eval("System.out.println(a);"); // 5
}

static JShell.Builder builder ()

Factory method for JShell.Builder which, in-turn, is used for creating instances of JShell.

final var os = new ByteArrayOutputStream();
try (final var ps = new PrintStream(os)) {

    final var builder = JShell.builder();
    try (final var js = builder.out(ps).build()) {
        js.eval("""
                System.out.println("abcd");
                """);
    }
}

System.out.println(os); // "abcd"

void close ()

Close this state engine.

An example with try-with-resources.

try (final var js = JShell.create()) {
    js.eval("System.out.println(\"abcd\");"); // "abcd"
}

An example without try-with-resources.

final var js = JShell.create();
try {
    js.eval("System.out.println(\"abcd\");"); // "abcd"
} finally {
    js.close();
}

static JShell create ()

Create a new JShell state engine.

try (final var js = JShell.create()) {

    js.eval("int x = 2;");
    js.eval("int y = 3;");
    js.eval("int z = x * y;");

    js.variables().forEach(varSnippet -> {
        System.out.printf("source [ %s ] : value [ %s ]%n",
                varSnippet.source(), js.varValue(varSnippet));
    });
}

// Result
// ↓
//source [ int x = 2; ] : value [ 2 ]
//source [ int y = 3; ] : value [ 3 ]
//source [ int z = x * y; ] : value [ 6 ]

Stream<Diag> diagnostics (Snippet snippet)

Return the diagnostics of the most recent evaluation of the snippet.

try (final var js = JShell.create()) {
    // This input code is intentionally missing.
    final var events = js.eval("int x = ");

    events.forEach(event -> {
        System.out.println(event.status()); // REJECTED

        js.diagnostics(event.snippet()).forEach(diag -> {

            System.out.println(diag.isError()); // true
            System.out.println(diag.getCode()); // compiler.err.premature.eof

            // "reached end of file while parsing"
            System.out.println(diag.getMessage(Locale.getDefault()));
        });
    });
}

List<SnippetEvent> drop (Snippet snippet)

Remove a declaration from the state.

try (final var js = JShell.create()) {

    final var events1 = js.eval("int x = 1;");
    events1.forEach(event -> {
        System.out.println(event.status()); // VALID
    });

    final var events2 = js.eval("System.out.println(x);"); // 1
    events2.forEach(event -> {
        System.out.println(event.status()); // VALID
    });

    // Drop the variable x.
    events1.forEach(event -> {
        js.drop(event.snippet());
    });

    final var events3 = js.eval("System.out.println(x);");
    events3.forEach(event -> {
        System.out.println(event.status()); // REJECTED

        js.diagnostics(event.snippet()).forEach(diag -> {
            //cannot find symbol
            //  symbol:   variable x
            //  location: class
            System.out.println(diag.getMessage(Locale.getDefault()));
        });
    });
}

List<SnippetEvent> eval (String input)

Evaluate the input String, including definition and/or execution, if applicable.

try (final var js = JShell.create()) {

    js.eval("int x = 2;");
    js.eval("int y = 3;");
    js.eval("int z = x * y;");

    js.variables().forEach(varSnippet -> {
        System.out.printf("source [ %s ] : value [ %s ]%n",
                varSnippet.source(), js.varValue(varSnippet));
    });
}

// Result
// ↓
//source [ int x = 2; ] : value [ 2 ]
//source [ int y = 3; ] : value [ 3 ]
//source [ int z = x * y; ] : value [ 6 ]
try (final var js = JShell.create()) {

    js.eval("""
            class A {
                String getMessage() {
                   return "abcd";
                }
            }
            """);

    js.eval("var a = new A();");
    js.eval("var message = a.getMessage();");

    js.eval("System.out.println(message);"); // "abcd"
}

Stream<ImportSnippet> imports ()

Returns the active import snippets.

try (final var js = JShell.create()) {

    js.eval("import java.nio.file.Path;");
    js.eval("import java.time.LocalDate;");

    final var imports = js.imports();

    imports.forEach(importSnippet -> {
        System.out.println(importSnippet);
    });

    // Result
    // ↓
    //Snippet:ImportKey(Path,SINGLE_TYPE_IMPORT_SUBKIND)#1-import java.nio.file.Path;
    //Snippet:ImportKey(LocalDate,SINGLE_TYPE_IMPORT_SUBKIND)#2-import java.time.LocalDate;
}

Stream<MethodSnippet> methods ()

Returns the active method snippets.

try (final var js = JShell.create()) {

    js.eval("int sum(int x, int y) { return x + y; }");

    js.eval("int a = sum(2, 3);");
    js.eval("System.out.println(a);"); // 5

    js.eval("int sub(int x, int y) { return x - y; }");

    js.eval("int b = sub(10, 2);");
    js.eval("System.out.println(b);"); // 8

    final var methods = js.methods();

    System.out.println("-- methods --");
    methods.forEach(methodSnippet -> {
        System.out.println(methodSnippet);
    });

    // Result
    // ↓
    //-- methods --
    //MethodSnippet:sum/(int,int)int-int sum(int x, int y) { return x + y; }
    //MethodSnippet:sub/(int,int)int-int sub(int x, int y) { return x - y; }
}

JShell.Subscription onShutdown (Consumer<JShell> listener)

Register a callback to be called when this JShell instance terminates.

final var listener = new Consumer<JShell>() {
    @Override
    public void accept(JShell jShell) {
        System.out.println("shutdown!");
    }
};

System.out.println("-- start --");

try (final var js = JShell.create()) {

    js.onShutdown(listener);

    js.eval("int a = 2 + 3;");
    js.eval("System.out.println(a);");
}

System.out.println("-- end --");

// Result
// ↓
//-- start --
//5
//shutdown!
//-- end --

JShell.Subscription onSnippetEvent (Consumer<SnippetEvent> listener)

Register a callback to be called when the Status of a snippet changes.

final var listener = new Consumer<SnippetEvent>() {
    @Override
    public void accept(SnippetEvent event) {
        System.out.println("  -- onSnippetEvent start --");
        System.out.println("  event : " + event.status());

        final var snippet = event.snippet();
        System.out.println("  snippet kind : " + snippet.kind());
        System.out.println("  snippet source : " + snippet.source());

        System.out.println("  -- onSnippetEvent end --");
    }
};

System.out.println("-- start --");

try (final var js = JShell.create()) {

    js.onSnippetEvent(listener);

    js.eval("int a = 2 + 3;");
    js.eval("System.out.println(\"a = \" + a);");

}

System.out.println("-- end --");

// Result
// ↓
//-- start --
//  -- onSnippetEvent start --
//  event : VALID
//  snippet kind : VAR
//  snippet source : int a = 2 + 3;
//  -- onSnippetEvent end --
//a = 5
//  -- onSnippetEvent start --
//  event : VALID
//  snippet kind : STATEMENT
//  snippet source : System.out.println("a = " + a);
//  -- onSnippetEvent end --
//-- end --

Stream<Snippet> snippets ()

Return all snippets.

try (final var js = JShell.create()) {

    js.eval("int x = 2;");
    js.eval("int y = 3;");
    js.eval("int a = x + y;");
    js.eval("System.out.println(a);"); // 5

    final var snippets = js.snippets();

    System.out.println("-- snippets --");
    snippets.forEach(snippet -> {
        System.out.println(snippet);
    });

    // Result
    // ↓
    //-- snippets --
    //Snippet:VariableKey(x)#1-int x = 2;
    //Snippet:VariableKey(y)#2-int y = 3;
    //Snippet:VariableKey(a)#3-int a = x + y;
    //Snippet:StatementKey#4-System.out.println(a);
}

SourceCodeAnalysis sourceCodeAnalysis ()

Access to source code analysis functionality.

try (final var js = JShell.create()) {

    final var analysis = js.sourceCodeAnalysis();

    final var input = """
            int sum(int x, int y) { return x + y; }
            System.out.println(sum(2, 3));
            """;

    // The input string with more than one snippet will fail.
    js.eval(input).forEach(event -> {
        System.out.println(event.status()); // REJECTED
    });

    final var completion = analysis.analyzeCompletion(input);

    final var source = completion.source();
    System.out.println(source); // int sum(int x, int y) { return x + y; }

    js.eval(source).forEach(event -> {
        System.out.println(event.status()); // VALID
    });

    final var remaining = completion.remaining();
    System.out.println(remaining); // System.out.println(sum(2, 3));

    js.eval(remaining); // 5
}

Snippet.Status status (Snippet snippet)

Return the status of the snippet.

try (final var js = JShell.create()) {

    js.eval("int x = 2;");
    js.eval("int y = 3;");

    // This input code is intentionally missing.
    js.eval("int z = x * ");

    System.out.println("-- status --");
    js.snippets().forEach(snippet -> {
        final var status = js.status(snippet);
        System.out.println(status);
    });

    // Result
    // ↓
    //-- status --
    //VALID
    //VALID
    //REJECTED
}

void stop ()

Attempt to stop currently running evaluation.

final var scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

try (final var js = JShell.create()) {

    scheduledExecutorService.schedule(() -> {
        System.out.println("-- JShell stop! --");
        js.stop();
    }, 2, TimeUnit.SECONDS);

    final var start = System.nanoTime();

    System.out.println("sleep start");
    js.eval("Thread.sleep(5000);");
    System.out.println("sleep end : " + (System.nanoTime() - start) / 1000000000.0 + " sec.");

} finally {
    scheduledExecutorService.shutdown();
}

final var ret = scheduledExecutorService.awaitTermination(10, TimeUnit.SECONDS);
System.out.println("term : " + ret);

// Result
// ↓
//sleep start
//-- JShell stop! --
//sleep end : 2.0477107 sec.
//term : true

Stream<TypeDeclSnippet> types ()

Returns the active type declaration (class, interface, annotation type, and enum) snippets.

try (final var js = JShell.create()) {

    js.eval("""
            class A {
                String getMessage() {
                   return "abcd";
                }
            }
            """);
    js.eval("var a = new A();");
    js.eval("System.out.println(a.getMessage());"); // "abcd"

    js.eval("""
            class B {
            }
            """);

    final var types = js.types();

    System.out.println("-- types --");
    types.forEach(type -> {
        System.out.println(type);
    });

    // Result
    // ↓
    //-- types --
    //Snippet:ClassKey(A)#1-class A {
    //    String getMessage() {
    //       return "abcd";
    //    }
    //}
    //
    //Snippet:ClassKey(B)#4-class B {
    //}
}

Stream<String> unresolvedDependencies (DeclarationSnippet snippet)

For RECOVERABLE_DEFINED or RECOVERABLE_NOT_DEFINED declarations, the names of current unresolved dependencies for the snippet.

try (final var js = JShell.create()) {

    final var events = js.eval("int calc(int x) { return x * AAA; } ");

    events.forEach(event -> {
        System.out.println(event.status()); // RECOVERABLE_DEFINED

        if (event.snippet() instanceof DeclarationSnippet snippet) {

            final var stream = js.unresolvedDependencies(snippet);
            stream.forEach(s -> {
                // "variable AAA"
                System.out.println(s);
            });
        }
    });

    js.eval("var AAA = 3;");
    js.eval("System.out.println(calc(10));"); // 30
}

void unsubscribe (JShell.Subscription token)

Cancel a callback subscription.

try (final var js = JShell.create()) {

    js.onShutdown(j -> {
        System.out.println("shutdown!");
    });

    js.eval("System.out.println(\"abcd\");"); // "abcd"
}

// Result
// ↓
//abcd
//shutdown!
try (final var js = JShell.create()) {

    final var token = js.onShutdown(j -> {
        System.out.println("shutdown!");
    });

    js.eval("System.out.println(\"abcd\");"); // "abcd"

    js.unsubscribe(token);
}

// Result
// ↓
//abcd

Stream<VarSnippet> variables ()

Returns the active variable snippets.

Please see eval(String input).

String varValue (VarSnippet snippet)

Get the current value of a variable.

Please see eval(String input).


To top of page