BLOG POSTS
Java REPL (JShell) Tutorial

Java REPL (JShell) Tutorial

Java’s REPL environment, officially called JShell and introduced in Java 9, brings the interactive programming experience that languages like Python and Ruby have had for years. This command-line tool lets you experiment with Java code snippets, test APIs, and prototype solutions without the ceremony of creating full classes and main methods. We’ll walk through everything from basic usage to advanced features, explore real-world applications, and compare JShell with alternatives to help you integrate this powerful tool into your development workflow.

How JShell Works Under the Hood

JShell operates on the Java Platform Module System and leverages the Compiler API to provide real-time compilation and execution. Unlike traditional Java development where you write complete programs, JShell maintains an internal state that persists variables, methods, and imports across multiple statements.

The tool uses a read-eval-print loop that:

  • Parses your input for syntactic correctness
  • Compiles valid Java expressions, statements, or declarations
  • Executes the compiled bytecode in an isolated environment
  • Displays results and maintains session state
  • Handles dependencies and classpath modifications dynamically

JShell runs on the same JVM as your regular Java applications but provides enhanced error recovery and allows incomplete code snippets that wouldn’t compile in standard Java.

Getting Started with JShell

JShell comes bundled with Java 9+ installations. To launch it, simply run:

jshell

You’ll see the JShell prompt:

|  Welcome to JShell -- Version 17.0.2
|  For an introduction type: /help intro

jshell>

Let’s start with basic operations:

jshell> int x = 42
x ==> 42

jshell> String greeting = "Hello JShell"
greeting ==> "Hello JShell"

jshell> System.out.println(greeting + " " + x)
Hello JShell 42

jshell> Math.sqrt(x)
$4 ==> 6.48074069840786

Notice how JShell automatically creates variable names like $4 for unnamed results. You can reference these later:

jshell> double result = $4 * 2
result ==> 12.96148139681572

Essential JShell Commands and Features

JShell provides numerous commands starting with forward slash. Here are the most useful ones:

Command Description Example
/help Display help information /help intro
/vars List all variables /vars
/methods List all methods /methods
/imports Show current imports /imports
/save Save session to file /save mysession.jsh
/open Load file into session /open mysession.jsh
/exit Exit JShell /exit

Creating methods in JShell is straightforward:

jshell> int factorial(int n) {
   ...>     if (n <= 1) return 1;
   ...>     return n * factorial(n - 1);
   ...> }
|  created method factorial(int)

jshell> factorial(5)
$7 ==> 120

You can also define classes:

jshell> class Person {
   ...>     private String name;
   ...>     private int age;
   ...>     
   ...>     public Person(String name, int age) {
   ...>         this.name = name;
   ...>         this.age = age;
   ...>     }
   ...>     
   ...>     public String toString() {
   ...>         return name + " (" + age + ")";
   ...>     }
   ...> }
|  created class Person

jshell> Person p = new Person("Alice", 30)
p ==> Alice (30)

Advanced JShell Features

JShell supports external JARs and custom classpaths. Start JShell with additional libraries:

jshell --class-path /path/to/your/library.jar

Or add dependencies during runtime:

jshell> /env --class-path /path/to/library.jar

For Maven dependencies, you can use third-party plugins or manually download JARs.

JShell also supports custom startup scripts. Create a file with common imports and utilities:

// startup.jsh
import java.util.*;
import java.util.stream.*;
import java.time.*;
import java.nio.file.*;

void print(Object obj) {
    System.out.println(obj);
}

List<String> readLines(String filename) throws Exception {
    return Files.readAllLines(Paths.get(filename));
}

Load it when starting JShell:

jshell --startup startup.jsh

Real-World Use Cases and Examples

JShell excels in several practical scenarios:

API Exploration and Testing

When working with unfamiliar libraries, JShell lets you experiment interactively:

jshell> import java.time.*

jshell> LocalDateTime now = LocalDateTime.now()
now ==> 2024-01-15T14:30:45.123456

jshell> now.plusDays(30).format(DateTimeFormatter.ISO_LOCAL_DATE)
$3 ==> "2024-02-14"

jshell> Duration.between(now, now.plusHours(5)).toMinutes()
$4 ==> 300

Data Processing and Analysis

Perfect for quick data manipulation tasks:

jshell> List<String> data = List.of("apple,5", "banana,3", "orange,8")

jshell> Map<String, Integer> inventory = data.stream()
   ...>     .map(s -> s.split(","))
   ...>     .collect(Collectors.toMap(
   ...>         arr -> arr[0],
   ...>         arr -> Integer.parseInt(arr[1])
   ...>     ))
inventory ==> {orange=8, banana=3, apple=5}

jshell> inventory.values().stream().mapToInt(Integer::intValue).sum()
$6 ==> 16

Algorithm Prototyping

Test algorithms before implementing them in production code:

jshell> boolean isPalindrome(String s) {
   ...>     s = s.toLowerCase().replaceAll("[^a-z0-9]", "");
   ...>     return s.equals(new StringBuilder(s).reverse().toString());
   ...> }

jshell> isPalindrome("A man, a plan, a canal: Panama")
$8 ==> true

Performance Considerations and Benchmarking

While JShell isn’t designed for production workloads, it handles moderate computational tasks well. Here’s a simple benchmarking approach:

jshell> long benchmark(Runnable task, int iterations) {
   ...>     long start = System.nanoTime();
   ...>     for (int i = 0; i < iterations; i++) {
   ...>         task.run();
   ...>     }
   ...>     return System.nanoTime() - start;
   ...> }

jshell> long time1 = benchmark(() -> new ArrayList<>(1000), 10000)
time1 ==> 12458792

jshell> long time2 = benchmark(() -> new LinkedList<>(), 10000)  
time2 ==> 8934563

jshell> System.out.printf("ArrayList: %.2f ms, LinkedList: %.2f ms%n", 
   ...>     time1/1_000_000.0, time2/1_000_000.0)
ArrayList: 12.46 ms, LinkedList: 8.93 ms

JShell vs Alternative REPLs

Feature JShell Groovy Console Scala REPL Kotlin REPL
Pure Java Syntax
Built-in with JDK
Tab Completion Limited
Session Persistence Limited Limited
Learning Curve Low Medium High Medium

JShell’s main advantage is its seamless integration with standard Java, making it ideal for Java developers who want to stay within their familiar syntax.

Best Practices and Common Pitfalls

Do’s:

  • Use meaningful variable names even in REPL sessions for better readability
  • Save important sessions with /save before closing
  • Create startup scripts for frequently used imports and utility methods
  • Use /vars and /methods to track your session state
  • Leverage tab completion for faster coding

Don’ts:

  • Don’t rely on JShell for performance-critical testing
  • Avoid complex multi-file projects in JShell
  • Don’t expect full IDE features like debugging or refactoring
  • Don’t use it as a replacement for proper unit testing

Common Issues and Solutions:

Problem: ClassNotFoundException when loading external JARs

Solution: Ensure JAR paths are absolute and use the /env --class-path command

Problem: Unable to modify previously defined methods

Solution: Simply redefine the method; JShell will replace the previous version

Problem: Session becomes cluttered with variables

Solution: Use /reset to start fresh, or /drop to remove specific elements

Integration with Development Workflows

JShell integrates well with modern development environments. Many IDEs now support JShell integration:

  • IntelliJ IDEA has built-in JShell console support
  • Eclipse provides JShell integration through plugins
  • VS Code offers JShell extensions for interactive Java development

For server environments, particularly when working with VPS instances or dedicated servers, JShell proves invaluable for quick diagnostics and testing without deploying full applications.

Consider creating shell aliases for common JShell configurations:

# Add to .bashrc or .zshrc
alias jshell-web="jshell --class-path /path/to/web-libs/*"
alias jshell-data="jshell --startup data-analysis-startup.jsh"

The official JShell documentation provides comprehensive coverage of advanced features and configuration options. JShell transforms Java development from a compile-heavy process into an interactive exploration tool, making it easier to learn APIs, prototype solutions, and validate ideas quickly.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked