Runnable sources, broken examples and captured transcripts for the ankurm.com JEP 513 article, including the JDK 25 vs 27 compiler wording differences. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01TF9JWFvJSNm6HVzswzZU5a
49 lines
2.9 KiB
Bash
Executable File
49 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# JEP 513 (Flexible Constructor Bodies): final in JDK 25, no --enable-preview.
|
|
# Regenerates every file in output/. JDK25=/path JDK27=/path [JDK21=/path] ./run.sh
|
|
set -uo pipefail
|
|
unset JAVA_TOOL_OPTIONS
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
JDK25="${JDK25:-/opt/jdks/jdk-25.0.4.1+1}"; JDK27="${JDK27:-/opt/jdks/jdk27}"; JDK21="${JDK21:-}"
|
|
OUT="$HERE/output"; mkdir -p "$OUT"; B="$(mktemp -d)"; trap 'rm -rf "$B"' EXIT
|
|
cd "$HERE"
|
|
v() { "$1/bin/java" -version 2>&1 | sed -n 2p; }
|
|
# compile SRC with JDK, then run CLASS from it; prints a header naming the JDK
|
|
cr() { local jdk="$1" src="$2" cls="$3"; local o="$B/$(basename "$jdk")-$cls"; mkdir -p "$o"
|
|
echo "\$ javac $src && java $cls ($(v "$jdk"))"
|
|
"$jdk/bin/javac" -d "$o" "$src" 2>&1 && "$jdk/bin/java" -cp "$o" "$cls" 2>&1; }
|
|
|
|
{ cr "$JDK25" src/ValidateBeforeSuper.java ValidateBeforeSuper; echo; cr "$JDK27" src/ValidateBeforeSuper.java ValidateBeforeSuper
|
|
} > "$OUT/01-validate-before-super.txt"
|
|
|
|
{ cr "$JDK25" src/BeforeJava25.java BeforeJava25
|
|
[ -n "$JDK21" ] && { echo; cr "$JDK21" src/BeforeJava25.java BeforeJava25; }
|
|
} > "$OUT/02-the-old-workaround.txt"
|
|
|
|
{ [ -n "$JDK21" ] && { cr "$JDK21" broken/OnJdk21.java OnJdk21; echo; }
|
|
cr "$JDK25" broken/OnJdk21.java OnJdk21; echo; cr "$JDK27" broken/OnJdk21.java OnJdk21
|
|
} > "$OUT/03-same-file-on-21-25-27.txt"
|
|
|
|
{ cr "$JDK25" src/OverridableCall.java OverridableCall; } > "$OUT/04-overridable-call-bug-and-fix.txt"
|
|
|
|
{ cr "$JDK25" src/ParseThenSuper.java ParseThenSuper; echo; cr "$JDK25" src/TryInPrologue.java TryInPrologue; echo; cr "$JDK25" src/ThisChaining.java ThisChaining
|
|
} > "$OUT/05-prologue-in-practice.txt"
|
|
|
|
{ o="$B/bc"; mkdir -p "$o"; "$JDK25/bin/javac" -d "$o" src/PrologueBytecode.java 2>&1
|
|
echo "\$ javap -c -p 'PrologueBytecode\$Child' ($(v "$JDK25"))"; "$JDK25/bin/javap" -c -p -cp "$o" 'PrologueBytecode$Child' 2>&1 | sed -n '2,$p'
|
|
} > "$OUT/06-bytecode.txt"
|
|
|
|
# the rules that did not go away: same source, both JDKs, because the wording changed between 25 and 27
|
|
{ for f in ReadFieldBeforeSuper CallMethodBeforeSuper PassThisBeforeSuper ReadFinalBeforeAssign InnerOuterThis NewInnerBeforeSuper AssignFieldWithInitializer AssignInheritedField ReturnBeforeSuper SuperInBranch TwoSuperCalls; do
|
|
for j in "$JDK25" "$JDK27"; do
|
|
echo "\$ javac broken/$f.java ($(v "$j" | sed 's/.*Temurin-//;s/ (build.*//'))"
|
|
"$j/bin/javac" -d "$B/x" broken/$f.java 2>&1 | grep -E 'error|warning' | sed 's/^broken\///'
|
|
done; echo
|
|
done
|
|
} > "$OUT/07-still-illegal-25-vs-27.txt"
|
|
# 08 - the language level matters: compiling this source for an older target from JDK 25
|
|
{ for r in 21 24 25; do echo "\$ javac --release $r broken/OnJdk21.java ($(v "$JDK25" | sed 's/.*Temurin-//;s/ (build.*//'))"
|
|
"$JDK25/bin/javac" --release $r -d "$B/r$r" broken/OnJdk21.java 2>&1 | grep -v '^Note:' | sed 's/^broken\///'; echo "exit=${PIPESTATUS[0]}"; echo; done
|
|
} > "$OUT/08-release-levels.txt"
|
|
echo "wrote $OUT"
|