Windows Native Access
On Windows, Æsh Readline needs access to the Windows Console API (Kernel32) for raw terminal input, console mode control, and terminal size detection. The terminal-tty module ships as a multi-release JAR with two implementations:
| Java Version | Implementation | Native Code Required |
|---|---|---|
| 8 – 21 | JNI (aesh-console.dll) | Yes |
| 22+ | FFM (java.lang.foreign) | No |
On Java 22+, the Foreign Function & Memory API calls Kernel32 directly from pure Java – no DLL, no native compilation, no cross-compiler toolchain.
Runtime Requirements
Java 22+
Applications running on Java 22+ must enable native access for the FFM API:
java --enable-native-access=ALL-UNNAMED -jar myapp.jarWithout this flag, Java 22-23 prints a warning and Java 24+ throws an IllegalCallerException.
Java 23+
Starting with Java 23, the JVM also warns when JNI loads native libraries without --enable-native-access. This means the flag is required on Java 23+ regardless of which implementation is active. The FFM path is the better choice here since it eliminates the DLL entirely.
Java 8 – 22
No special flags are needed. The JNI implementation loads aesh-console.dll from the JAR automatically.
How It Works
The multi-release JAR contains two versions of WinConsoleNative:
terminal-tty.jar
├── org/aesh/terminal/tty/impl/WinConsoleNative.class (JNI, Java 8)
├── META-INF/versions/22/org/aesh/terminal/tty/impl/WinConsoleNative.class (FFM, Java 22+)
├── META-INF/MANIFEST.MF (Multi-Release: true)
└── native/windows-x86_64/aesh-console.dll (for JNI fallback)The JVM automatically selects the correct class based on the runtime version. No configuration or code changes are needed – callers like WinSysTerminal and AbstractWindowsTerminal use the same API regardless of which implementation is active.
Both implementations wrap these Windows Console API functions:
| Function | Purpose |
|---|---|
GetStdHandle | Obtain stdin/stdout/stderr handles |
GetConsoleMode / SetConsoleMode | Control raw mode, echo, VT processing, mouse input |
GetConsoleOutputCP | Detect console encoding |
GetConsoleScreenBufferInfo | Query terminal width and height |
ReadConsoleInputW | Read key events, mouse events, and window resize events |
WriteConsoleW | Write Unicode output to the console |
Building from Source
The multi-release JAR is built automatically based on the JDK used:
With Java 22+ – produces a multi-release JAR with both JNI and FFM variants:
export JAVA_HOME=/path/to/jdk-24
mvn clean packageWith Java 8-21 – produces a standard JAR with only the JNI variant:
export JAVA_HOME=/path/to/jdk-21
mvn clean packageFor releases, build with Java 22+ to include the FFM implementation.
GraalVM Native Image
The FFM implementation is compatible with GraalVM native-image (25+). For GraalVM 23-24, use the JNI implementation – the resource-config.json in the JAR ensures the DLL is included in native images.
Maven Configuration for Downstream Projects
If your project uses maven-surefire-plugin or maven-exec-plugin and runs on Java 22+, add the native access flag:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--enable-native-access=ALL-UNNAMED</argLine>
</configuration>
</plugin>To avoid breaking builds on older JDKs, use a profile:
<profile>
<id>java22-native-access</id>
<activation>
<jdk>[22,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--enable-native-access=ALL-UNNAMED</argLine>
</configuration>
</plugin>
</plugins>
</build>
</profile>Cygwin and MSYS2
When running under Cygwin or MSYS2, Æsh Readline detects the POSIX-compatible environment and uses PTY-based terminal access instead of the Windows Console API. Neither JNI nor FFM is used in this case.