Terminal Providers
JLine supports multiple terminal providers, each with its own characteristics and capabilities. This allows JLine to work across different platforms and environments.
JLine 4.x has removed the JNA and Jansi providers. These providers are no longer available and have been replaced by more modern alternatives.
The recommended providers for JLine 4.x are JNI (for maximum compatibility) and FFM (for best performance on Java 22+).
Provider Selection
JLine can automatically select the best terminal provider for your environment, or you can explicitly specify which provider to use:
Loading snippet: ProviderSelectionExample...
JNA Provider (Removed in JLine 4.x)
The JNA (Java Native Access) provider has been removed in JLine 4.x. Use the JNI or FFM providers instead for native terminal functionality.
Jansi Provider (Removed in JLine 4.x)
The Jansi provider has been removed in JLine 4.x. Use the JNI or FFM providers instead for ANSI support and terminal functionality.
FFM Provider
The FFM (Foreign Function & Memory) provider uses Java's FFM API (available in Java 22+) to access native terminal functionality:
Loading snippet: FfmTerminalExample...
The FFM provider is compiled with Java 22 bytecode and requires:
- Java 22 or later to run
- Native access permissions at runtime:
--enable-native-access=org.jline.terminal.ffm(module path) or--enable-native-access=ALL-UNNAMED(classpath)
If you're using Java 11-21, the FFM provider will be automatically skipped during provider selection, or you can use the jdk11 classifier to exclude it entirely from your classpath.
See JPMS documentation for more details on native access configuration.
Using the JDK11 Classifier
If you're building your project with Java 11-21 and want to avoid Java 22 class files in your dependencies, use the jdk11 classifier for the jline bundle:
Maven:
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
<version>4.0.0</version>
<classifier>jdk11</classifier>
</dependency>
Gradle:
implementation 'org.jline:jline:4.0.0:jdk11'
The jdk11 classifier artifact:
- Excludes the
org.jline.terminal.impl.ffm.*classes (compiled with Java 22) - Contains all other JLine functionality
- Compatible with Java 11-21
- Automatically uses JNI or Exec providers for native terminal access
This is particularly useful when:
- Your build tools warn about class file version mismatches
- You're targeting Java 21 or earlier
- You need to avoid dependencies with newer bytecode versions
Note: For JLine 3.x, use the jdk8 classifier which is compatible with Java 8-21.
JNI Provider
The JNI (Java Native Interface) provider uses JNI to access native terminal functionality:
Loading snippet: JniTerminalExample...
Exec Provider
The Exec provider uses external commands to access terminal functionality:
Loading snippet: ExecTerminalExample...
Dumb Terminal
The Dumb terminal is a fallback option that provides basic terminal functionality without advanced features:
Loading snippet: DumbTerminalExample...
Using JLine for ANSI Output Only (No Native Access)
If you only need JLine for generating ANSI escape sequences (styled/colored text output) and don't need interactive line editing or terminal control, you can use JLine without any native access at all.
Minimal Dependencies
The jline-terminal module contains AttributedString, AttributedStyle, and AttributedStringBuilder in the org.jline.utils package. These classes generate ANSI escape sequences without requiring any native code:
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-terminal</artifactId>
<version>4.0.0</version>
</dependency>
Generating ANSI Sequences Without a Terminal
AttributedString.toAnsi() can be called without a terminal instance:
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.AttributedStyle;
// Build styled text
AttributedStringBuilder sb = new AttributedStringBuilder();
sb.style(AttributedStyle.DEFAULT.foreground(AttributedStyle.RED).bold());
sb.append("Error: ");
sb.style(AttributedStyle.DEFAULT);
sb.append("something went wrong");
// Convert to ANSI escape sequence string — no terminal needed
String ansi = sb.toAnsi();
System.out.println(ansi);
This produces: \033[1;31mError: \033[0msomething went wrong
Available Style Attributes
AttributedStyle supports:
- Text attributes:
bold(),faint(),italic(),underline(),blink(),inverse(),conceal(),crossedOut() - Standard colors (0-7):
foreground(AttributedStyle.RED),background(AttributedStyle.BLUE) - 256-color palette:
foreground(196)(indexed color) - 24-bit true color:
foreground(r, g, b)
When You Need a Terminal
If you need a Terminal object (e.g., for toAnsi(Terminal) to adapt output to terminal capabilities) but don't want native access, use the exec or dumb provider:
// Exec provider: uses external commands (stty), no native libraries
Terminal terminal = TerminalBuilder.builder()
.provider("exec")
.build();
// Dumb provider: pure Java, no external commands, no native access
Terminal terminal = TerminalBuilder.builder()
.dumb(true)
.build();
The exec provider gives full terminal capabilities on Unix-like systems by spawning external commands (stty, tput) instead of loading native libraries. The dumb provider is a pure-Java fallback with no native access at all.
Which Provider Needs Native Access?
| Provider | Native Access | Java Version | Capabilities |
|---|---|---|---|
| FFM | Yes | 22+ | Full terminal control via Foreign Function & Memory API |
| JNI | Yes | 11+ | Full terminal control via Java Native Interface |
| Exec | No | 11+ | Full terminal control via external commands (Unix) |
| Dumb | No | 11+ | Basic I/O only, no terminal control |
| No terminal | No | 11+ | ANSI generation only (AttributedString.toAnsi()) |
Migrating from Jansi
If you previously used Jansi purely for ANSI output generation, the migration is straightforward:
| Jansi | JLine 4 Equivalent |
|---|---|
Ansi.ansi().fg(RED).a("text").reset() | new AttributedString("text", AttributedStyle.DEFAULT.foreground(RED)).toAnsi() |
Ansi.ansi().bold().a("text").reset() | new AttributedString("text", AttributedStyle.BOLD).toAnsi() |
AnsiConsole.systemInstall() | Not needed — modern Windows terminals support ANSI natively |
AnsiConsole.out().println(...) | System.out.println(attributedString.toAnsi()) |
For Windows ANSI support: Windows 10+ (including Windows Terminal, ConEmu, and modern cmd.exe) handles ANSI escape sequences natively. AnsiConsole.systemInstall() is no longer needed in most cases.
Best Practices
When working with terminal providers in JLine, consider these best practices:
-
Auto-Selection: Let JLine automatically select the best provider for your environment when possible.
-
Fallback Strategy: Implement a fallback strategy if a specific provider is not available.
-
Feature Detection: Check for terminal capabilities before using advanced features.
-
Cross-Platform Testing: Test your application on different platforms to ensure it works with different providers.
-
Error Handling: Handle terminal-related errors gracefully.
-
Terminal Cleanup: Always close the terminal when your application exits.
-
Signal Handling: Handle terminal signals (like SIGINT) appropriately.
-
Terminal Size: Be aware of terminal size and adapt your UI accordingly.
-
Color Support: Check for color support before using colors.
-
Documentation: Document which terminal providers your application supports.