nio2: NIO.2 file API companion code (streaming 5 GB at -Xmx64m, handle leaks, WatchService, mmap)

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KqJyCidz3ZgRyHABv2GVJh
This commit is contained in:
2026-09-30 19:14:31 +00:00
co-authored by Claude Sonnet 5.5
parent f4b732799d
commit 1ac2f6077a
30 changed files with 1072 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
# nio2
Companion code for the ankurm.com post *"Java NIO.2 File API: Files, Path, WatchService, and Streaming
Large Files Without OOM."* Module `nio2` in `java-core-examples`.
All explanation lives in the post; this module holds the runnable evidence and the captured output.
## Versions
| Component | Version |
|---|---|
| JDK | 25.0.4.1+1 (Temurin, LTS) |
| JUnit Jupiter | 5.11.0 |
| OS | Linux 6.18 (WatchService and `/proc/self/fd` results are Linux-specific) |
| Hardware | 2 vCPU x86-64 VM shared with other jobs (timings are indicative, not a leaderboard) |
| Big file | 5,000,000,069 bytes (the full 5 GB fit; the file is generated, then deleted by the script) |
## Quickstart
```bash
export JDK25_HOME=/path/to/jdk-25
./scripts/run-all.sh # needs ~5.3 GB free in /tmp/nio2-data; regenerates output/
BIG_BYTES=500000000 ./scripts/run-all.sh # smaller "big" file if disk is tight
mvn -q -pl nio2 -am test # 12 assertions, small files only
```
## What is in here
| File | Shows | Output |
|---|---|---|
| `LogFile` | deterministic generator for the synthetic log file | `02` |
| `StreamLines` | `Files.lines` and `Files.newBufferedReader` over 5 GB at `-Xmx64m`, heap and GC evidence | `03`, `04` |
| `ReadAllFail` | `readAllLines` / `readString` / `readAllBytes` at the same `-Xmx`, and how much heap they need | `05` |
| `HandleLeakDemo` | open file descriptors around unclosed `Files.lines` and `Files.walk` | `06` |
| `HandleExhaustion` | what an unclosed `Files.walk` becomes under `ulimit -n 64` | `07` |
| `WalkFindDemo` | `list` / `walk` / `find` / `walkFileTree` / `DirectoryStream`, symlink loop | `08` |
| `LinesCharsetDemo` | a bad byte fails lazily inside `Files.lines` | `09` |
| `WatchDemo` | WatchService events, coalescing, no recursion, OVERFLOW at 513 pending events | `10`, `11` |
| (JDK source excerpt) | `AbstractWatchKey.signalEvent` from the JDK's own `src.zip` | `12` |
| `MappedDemo` | 2 GiB classic `map` limit, Arena mapping, resident memory | `13` |
| `Nio2BehaviourTest` | 12 assertions behind the claims above | `14` |
`01` records the environment (kernel, JDK, `ulimit -n`, inotify limit, free disk).
Timings move with whatever else the machine is doing; counts, exceptions and GC figures do not.