# javademos Runnable companion code for the ankurm.com post **"Java 27 Is Out: Every JEP, Plus the Java 26 Changes You Skipped"**, for the Java version guides (), and for two standalone deep dives: **Stream Gatherers (JEP 485)** and **Scoped Values vs ThreadLocal (JEP 506)**. Every number and transcript in the post comes from a file in `docs/output/`, produced by a script in `scripts/`. ## What was tested against | Thing | Version | Note | |---|---|---| | JDK 21 (LTS) | Amazon Corretto 21.0.12.1 | the start of the 21 to 25 lane | | JDK 25 (LTS) | Temurin 25.0.4.1+1 | the baseline for "broke on 26" | | JDK 26 | Amazon Corretto 26.0.2.1 | GA 2026-03-17, non-LTS | | JDK 27 | Amazon Corretto 27+35 | GA 2026-09-15, non-LTS | | Containers | `amazoncorretto:23`, `:24` (when did it change?), `:26`, `:27` | same vendor for both, so only the JDK version changes | | JOL | 0.17 | downloaded and sha1-checked by `scripts/object-headers.sh` | Next LTS: Java 29, September 2027 (Oracle Java SE Support Roadmap). Layout: `g1-container/`, `object-headers/`, `jep-tour/` (27 features and `broken/` 26-era sources), `recap26/` (the Java 26 lane), `lanes/` (the 21 to 25 hub demos, the AI prompts in `lanes/prompts/` and the build-file demo in `lanes/upgrade/`), `other-changes/`, `api-diff/`, `gatherers/` (JEP 485, standalone post), `scoped-values/` (JEP 506 vs `ThreadLocal`, standalone post). ## Quickstart ```bash export JDK21=/path/to/jdk-21 JDK25=/path/to/jdk-25 JDK26=/path/to/jdk-26 JDK27=/path/to/jdk-27 # defaults are in scripts/env.sh ./scripts/jep-tour.sh # the five 27 feature demos, self-asserting ./scripts/recap26.sh # the 26 recap lane ./scripts/lanes.sh # the 21 to 25 hub claims, checked on 21, 23, 24, 25, 26, 27 ./scripts/upgrade.sh # the build-file half: Maven, Gradle, Lombok, --release, jdeps (needs Maven Central) ./scripts/gatherers.sh # Stream Gatherers (JEP 485): every built-in gatherer, a custom one, mapConcurrent ./scripts/scoped-values.sh # Scoped Values vs ThreadLocal (JEP 506): API, inheritance, memory (needs jcmd on PATH) ./scripts/run-all.sh # regenerate every docs/output/*.txt (about 15-20 minutes; needs Docker) ``` Timings, RSS, GC counts and the Vector species are machine dependent; treat them as shape, not results. Everything else is byte-stable. ## Chapters | # | Chapter | |---|---| | 1 | [What shipped, and what to believe](docs/01-what-shipped.md) | | 2 | [G1 becomes the default, even on one CPU (JEP 523)](docs/02-g1-default.md) | | 3 | [Compact object headers (JEP 534)](docs/03-compact-headers.md) | | 4 | [Post-quantum TLS (JEP 527)](docs/04-post-quantum-tls.md) | | 5 | [Primitive patterns (JEP 532)](docs/05-primitive-patterns.md) | | 6 | [Lazy constants (JEP 531)](docs/06-lazy-constants.md) | | 7 | [Structured concurrency (JEP 533)](docs/07-structured-concurrency.md) | | 8 | [PEM encodings (JEP 538)](docs/08-pem-api.md) | | 9 | [JFR redaction (JEP 536) and the Vector API (JEP 537)](docs/09-jfr-redaction-and-vector.md) | | 10 | [Other 27 changes](docs/10-other-27-changes.md) | | 11 | [Recap: the Java 26 changes you skipped](docs/11-recap-26.md) | | 12 | [Version lanes: 25 to 29](docs/12-lanes-25-to-29.md) | | 13 | [Upgrade checklist](docs/13-upgrade-checklist.md) | | 14 | [The 21 to 25 lane: every claim in the hub posts, checked](docs/14-lanes-21-to-25.md) | | 15 | [Build files: Maven, Gradle and Lombok on the way to 25](docs/15-build-files.md) | | 16 | [Stream Gatherers (JEP 485)](docs/16-gatherers.md) | | 17 | [Scoped values vs ThreadLocal (JEP 506)](docs/17-scoped-values-migration.md) | ## Standalone article modules (no `docs/` folder) These modules keep only sources, a `run.sh` and their transcripts (`output/`). The explanation lives in the article itself, in collapsible sections. | Module | Article | What it demonstrates | |---|---|---| | [`jep512/`](jep512) | Compact Source Files and Instance Main Methods in Java 25 (JEP 512) | `java Hello.java` on JDK 21 vs 25 vs 27, the class `javac` builds around `void main()`, implicit `java.base` imports, `java.lang.IO`, the measured launch order, a private-constructor difference between 25 and 27 | | [`jep513/`](jep513) | Flexible Constructor Bodies in Java 25 (JEP 513): Validate Before super() | statements before `super(...)`/`this(...)`, the parent-calls-child bug and its fix, twelve compile errors that remain with the 25 and 27 wordings side by side, `--release` rejection | | [`jep511/`](jep511) | Module Import Declarations in Java 25 (JEP 511) | `import module java.base;` against seven single imports, ambiguity errors and how single-type, on-demand and same-package names beat a module import, what one module import does and does not bring in (`java.sql` does not give `java.base`; `java.se` needs `--add-modules`), named modules, JEP 512 compact files, jshell's default imports, identical bytecode | | [`patterns/`](patterns) | Pattern Matching in Java: switch, Record Patterns and Primitive Patterns (JDK 21 to 27) | type and record patterns, guards and dominance errors, sealed exhaustiveness (with JDK 27's new `missing patterns` lines), `MatchException` from a throwing accessor and from separate compilation, unnamed patterns, primitive patterns with `--enable-preview` and the preview class-file trap | ## Captured output (`docs/output/`) | File | Produced by | What it is | |---|---|---| | `01`-`03` | `g1-default.sh` | which collector each JDK picks, by container size; the opt-out | | `04`-`06` | `g1-cost.sh`, `g1-tuning.sh` | what G1 costs on one CPU, and two tested explanations | | `10`-`15` | `object-headers.sh` | JOL instance sizes on 26, 27, 27 opted out; the JOL record failure and workaround | | `20-broken-*` | `broken-on-27.sh` | javac's own messages for 26-era preview code on 27 | | `21`-`25` | `jep-tour.sh` | the five 27 feature demos | | `30`-`32` | `tls-pq.sh` | key-exchange matrix, ClientHello size, the opt-out | | `40` | `jfr-redaction.sh` | five redaction configurations | | `50`-`52` | `api-diff.sh` | public API diffs, 26 to 27, 25 to 26, Vector only | | `60`-`62` | `other-changes.sh` | removed options, behaviour changes, new 27 API | | `70`-`75` | `recap26.sh` | final-field mutation, AOT cache matrix and startup, removals, 26 API, HTTP/3 | | `92`-`97` | `upgrade.sh` | Maven release 25 on JDK 21, 25, 27, Gradle 8 vs 9 on JDK 25, `--release` vs `-source/-target`, Lombok and Mockito by version, `jdeps --jdk-internals` | | `80`-`91` | `lanes.sh` | the 21 to 25 hub claims on JDK 21, 23, 24, 25, 26, 27: scoped values, structured concurrency, finalization, pinning, ZGC flags, warnings | | `98` | `gatherers.sh` | the four built-in gatherers, `mapConcurrent` + virtual threads, a custom `Gatherer`, Collector vs Gatherer | | `99` | `scoped-values.sh` | `ScopedValue` API and rebinding, why plain threads don't inherit a binding, memory vs `ThreadLocal` two ways (heap delta, then `jcmd` object census) | ## Not reproduced `jdk.java.net/27` and `openjdk.org/jeps` returned 403 while this was written; the JEP list was cross-checked against four secondary sources and the JDK binaries themselves. HTTP/3 was not spoken to a real HTTP/3 server (no UDP egress). JEP 522 was not benchmarked. JDK-8377013 could not be reproduced. MIT licensed, see `LICENSE`.