Files
javademos/README.md
T
Claude 6b5a918278 Add two standalone modules: Stream Gatherers (JEP 485) and Scoped Values vs ThreadLocal (JEP 506)
gatherers/: windowFixed, windowSliding, fold, scan, mapConcurrent, a custom
Gatherer (dedupeConsecutive, takeUntil), and a Collector-vs-Gatherer comparison.
Verified: windowSliding emits one short window on a too-short stream rather than
shrinking to empty like windowFixed; mapConcurrent waits for in-flight siblings
to finish (~901ms) rather than cancelling them when one mapper throws.

scoped-values/: ScopedValue API and rebinding, why plain threads (virtual or
platform) do not inherit a binding while a StructuredTaskScope subtask does,
and the memory cost vs InheritableThreadLocal measured two ways -- a noisy
heap-delta first pass, then a precise jcmd GC.class_histogram object census
(5 shared Carrier objects vs ~700,000 copied ThreadLocalMap/Entry objects for
100,000 threads).

Companion code for the ankurm.com posts "Java Stream Gatherers (JEP 485)" and
"Scoped Values vs ThreadLocal in Java 25: Migration Guide with Virtual Threads".

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FtpJvZfg4nvLvtzgJTDWpB
2026-09-24 04:27:12 +00:00

5.5 KiB

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 (https://ankurm.com/java-21-to-25-lts-features/), 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

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
2 G1 becomes the default, even on one CPU (JEP 523)
3 Compact object headers (JEP 534)
4 Post-quantum TLS (JEP 527)
5 Primitive patterns (JEP 532)
6 Lazy constants (JEP 531)
7 Structured concurrency (JEP 533)
8 PEM encodings (JEP 538)
9 JFR redaction (JEP 536) and the Vector API (JEP 537)
10 Other 27 changes
11 Recap: the Java 26 changes you skipped
12 Version lanes: 25 to 29
13 Upgrade checklist
14 The 21 to 25 lane: every claim in the hub posts, checked
15 Build files: Maven, Gradle and Lombok on the way to 25
16 Stream Gatherers (JEP 485)
17 Scoped values vs ThreadLocal (JEP 506)

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.