Skip to content

Commit 32bf73a

Browse files
committed
added windows docs
1 parent d4f9779 commit 32bf73a

1 file changed

Lines changed: 124 additions & 0 deletions

File tree

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
---
2+
date: '2026-04-18T12:00:00+02:00'
3+
draft: false
4+
title: 'Windows Native Access'
5+
weight: 16
6+
---
7+
8+
On Windows, Æsh Readline needs access to the Windows Console API (Kernel32) for raw terminal input, console mode control, and terminal size detection. Starting with version 3.6, the `terminal-tty` module ships as a **multi-release JAR** with two implementations:
9+
10+
| Java Version | Implementation | Native Code Required |
11+
|-------------|----------------|---------------------|
12+
| 8 -- 21 | JNI (`aesh-console.dll`) | Yes |
13+
| 22+ | FFM (`java.lang.foreign`) | No |
14+
15+
On Java 22+, the Foreign Function & Memory API calls Kernel32 directly from pure Java -- no DLL, no native compilation, no cross-compiler toolchain.
16+
17+
## Runtime Requirements
18+
19+
### Java 22+
20+
21+
Applications running on Java 22+ must enable native access for the FFM API:
22+
23+
```
24+
java --enable-native-access=ALL-UNNAMED -jar myapp.jar
25+
```
26+
27+
Without this flag, Java 22-23 prints a warning and Java 24+ throws an `IllegalCallerException`.
28+
29+
### Java 23+
30+
31+
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.
32+
33+
### Java 8 -- 22
34+
35+
No special flags are needed. The JNI implementation loads `aesh-console.dll` from the JAR automatically.
36+
37+
## How It Works
38+
39+
The multi-release JAR contains two versions of `WinConsoleNative`:
40+
41+
```
42+
terminal-tty.jar
43+
├── org/aesh/terminal/tty/impl/WinConsoleNative.class (JNI, Java 8)
44+
├── META-INF/versions/22/org/aesh/terminal/tty/impl/WinConsoleNative.class (FFM, Java 22+)
45+
├── META-INF/MANIFEST.MF (Multi-Release: true)
46+
└── native/windows-x86_64/aesh-console.dll (for JNI fallback)
47+
```
48+
49+
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.
50+
51+
Both implementations wrap these Windows Console API functions:
52+
53+
| Function | Purpose |
54+
|----------|---------|
55+
| `GetStdHandle` | Obtain stdin/stdout/stderr handles |
56+
| `GetConsoleMode` / `SetConsoleMode` | Control raw mode, echo, VT processing |
57+
| `GetConsoleOutputCP` | Detect console encoding |
58+
| `GetConsoleScreenBufferInfo` | Query terminal width and height |
59+
| `ReadConsoleInputW` | Read key events and window resize events |
60+
| `WriteConsoleW` | Write Unicode output to the console |
61+
62+
## Building from Source
63+
64+
The multi-release JAR is built automatically based on the JDK used:
65+
66+
**With Java 22+** -- produces a multi-release JAR with both JNI and FFM variants:
67+
68+
```bash
69+
export JAVA_HOME=/path/to/jdk-24
70+
mvn clean package
71+
```
72+
73+
**With Java 8-21** -- produces a standard JAR with only the JNI variant:
74+
75+
```bash
76+
export JAVA_HOME=/path/to/jdk-21
77+
mvn clean package
78+
```
79+
80+
For releases, build with Java 22+ to include the FFM implementation.
81+
82+
## GraalVM Native Image
83+
84+
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.
85+
86+
## Maven Configuration for Downstream Projects
87+
88+
If your project uses `maven-surefire-plugin` or `maven-exec-plugin` and runs on Java 22+, add the native access flag:
89+
90+
```xml
91+
<plugin>
92+
<groupId>org.apache.maven.plugins</groupId>
93+
<artifactId>maven-surefire-plugin</artifactId>
94+
<configuration>
95+
<argLine>--enable-native-access=ALL-UNNAMED</argLine>
96+
</configuration>
97+
</plugin>
98+
```
99+
100+
To avoid breaking builds on older JDKs, use a profile:
101+
102+
```xml
103+
<profile>
104+
<id>java22-native-access</id>
105+
<activation>
106+
<jdk>[22,)</jdk>
107+
</activation>
108+
<build>
109+
<plugins>
110+
<plugin>
111+
<groupId>org.apache.maven.plugins</groupId>
112+
<artifactId>maven-surefire-plugin</artifactId>
113+
<configuration>
114+
<argLine>--enable-native-access=ALL-UNNAMED</argLine>
115+
</configuration>
116+
</plugin>
117+
</plugins>
118+
</build>
119+
</profile>
120+
```
121+
122+
## Cygwin and MSYS2
123+
124+
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.

0 commit comments

Comments
 (0)