
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.