Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01B38FGKKam5SCGgwgduVAh3
111 lines
8.7 KiB
Bash
Executable File
111 lines
8.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# The build-file half of the 21 -> 25 upgrade guide (ankurm.com/java-21-to-25-upgrade-guide-ai-prompts), run for real.
|
|
# ./scripts/upgrade.sh -> docs/output/92-maven-release.txt, 93-gradle-toolchain.txt, 94-release-flag.txt,
|
|
# 95-lombok-matrix.txt, 96-jdeps-internals.txt, 97-mockito-bytebuddy.txt
|
|
# Needs Maven, Gradle 8.x and 9.x (GRADLE8 / GRADLE9), JDKs 21, 25, 26, 27 and network access to Maven Central.
|
|
# In a sandbox that reaches Maven Central through a proxy, export JAVA_TOOL_OPTIONS (the proxy trust store)
|
|
# before running: it is handed to Maven and Gradle below and unset for everything else by env.sh.
|
|
set -uo pipefail
|
|
NET_JTO="${JAVA_TOOL_OPTIONS:-}"
|
|
source "$(dirname "$0")/env.sh"
|
|
GRADLE8="${GRADLE8:-/opt/gradle-8.14.3}"; GRADLE9="${GRADLE9:-/opt/gradle-9.1.0}"
|
|
SRC="$ROOT/lanes/src"; UP="$ROOT/lanes/upgrade"; B="$ROOT/build/upgrade"; rm -rf "$B"; mkdir -p "$B"
|
|
jdk() { case "$1" in 21) echo "$JDK21";; 25) echo "$JDK25";; 26) echo "$JDK26";; 27) echo "$JDK27";; esac; }
|
|
scrub() { sed -i -E "s#$ROOT#<repo>#g; s#/opt/jdks/[^ ]*#<jdk>#g; s#/tmp/[^ ]*#<tmp>#g" "$@"; }
|
|
|
|
# ---------- 92: Maven, the three properties from Step 1 ----------
|
|
mvnrun() { local v="$1"; rm -rf "$B/mvn$v" && cp -r "$UP" "$B/mvn$v" && cd "$B/mvn$v" \
|
|
&& JAVA_HOME="$(jdk "$v")" MAVEN_OPTS="$NET_JTO" mvn -B -ntp package 2>&1 | grep -E '^\[(INFO|ERROR)\] (--- |BUILD|Compiling|Failed to execute|.*release version|Using|Building jar)|error: release' | sed -E 's/^/ /'; cd "$ROOT"; }
|
|
{
|
|
echo "# pom.xml sets maven.compiler.source/target/release to 25 (lanes/upgrade/pom.xml)"
|
|
echo; echo "\$ mvn package (build JDK 21)"; mvnrun 21
|
|
echo; echo "\$ mvn package (build JDK 25)"; mvnrun 25
|
|
echo; echo "\$ mvn package (build JDK 27, still release 25)"; mvnrun 27
|
|
echo; echo "\$ javap -v -cp target/classes demo.App | grep 'major version'"; "$(jdk 25)/bin/javap" -v -cp "$B/mvn25/target/classes" demo.App | grep 'major version' | sed 's/^ */ /'
|
|
echo; echo "\$ java -cp target/classes demo.App (JDK 25)"; "$JDK25/bin/java" -cp "$B/mvn25/target/classes" demo.App | sed 's/^/ /'
|
|
echo; echo "\$ java -cp target/classes demo.App (JDK 21: the class file is newer than the JVM)"; "$JDK21/bin/java" -cp "$B/mvn25/target/classes" demo.App 2>&1 | head -2 | sed 's/^/ /'
|
|
} > "$OUT/92-maven-release.txt" 2>&1
|
|
scrub "$OUT/92-maven-release.txt"
|
|
|
|
# ---------- 93: Gradle, the toolchain block from Step 1 ----------
|
|
# gradlerun <gradle home> <label> <JDK that runs Gradle itself>
|
|
gradlerun() { local g="$1" name="$2" runjdk="$3"; rm -rf "$B/gr$name" && cp -r "$UP" "$B/gr$name" && cd "$B/gr$name" \
|
|
&& JAVA_HOME="$runjdk" GRADLE_OPTS="$NET_JTO" "$g/bin/gradle" --no-daemon --console=plain -q \
|
|
-Porg.gradle.java.installations.paths="$JDK25" -Porg.gradle.java.installations.auto-download=false \
|
|
-Dorg.gradle.jvmargs="$NET_JTO" run 2>&1 | grep -v -E '^(Picked up|Starting a Gradle Daemon|$)' | head -3 | sed 's/^/ /'; cd "$ROOT"; }
|
|
{
|
|
echo "# build.gradle.kts asks for a Java 25 toolchain (lanes/upgrade/build.gradle.kts). Two questions: which JDK compiles, and which JDK runs Gradle itself?"
|
|
echo; echo "\$ gradle run (Gradle 8.14.3 running on JDK 21, toolchain finds JDK 25)"; gradlerun "$GRADLE8" 8-21 "$JDK21"
|
|
echo; echo "\$ gradle run (Gradle 8.14.3 running on JDK 25)"; gradlerun "$GRADLE8" 8-25 "$JDK25"
|
|
echo; echo "\$ gradle run (Gradle 9.1.0 running on JDK 25)"; gradlerun "$GRADLE9" 9-25 "$JDK25"
|
|
} > "$OUT/93-gradle-toolchain.txt" 2>&1
|
|
scrub "$OUT/93-gradle-toolchain.txt"
|
|
|
|
# ---------- 94: --release versus -source/-target ----------
|
|
mkdir -p "$B/rf-a" "$B/rf-b"
|
|
{
|
|
echo "# ReleaseFlag.java calls String.equalsFoldCase, which is new in Java 26. The compiler is JDK 27's javac both times."
|
|
echo; echo "\$ javac --release 25 ReleaseFlag.java"
|
|
out="$("$JDK27/bin/javac" --release 25 -d "$B/rf-a" "$SRC/ReleaseFlag.java" 2>&1)"; rc=$?; printf '%s\n' "$out" | sed 's/^/ /'; echo " exit=$rc"
|
|
echo; echo "\$ javac -source 25 -target 25 ReleaseFlag.java"
|
|
out="$("$JDK27/bin/javac" -source 25 -target 25 -d "$B/rf-b" "$SRC/ReleaseFlag.java" 2>&1)"; rc=$?; printf '%s\n' "$out" | sed 's/^/ /'; echo " exit=$rc"
|
|
echo; echo "\$ java -cp rf-b ReleaseFlag (JDK 25)"; "$JDK25/bin/java" -cp "$B/rf-b" ReleaseFlag 2>&1 | head -3 | sed 's/^/ /'
|
|
echo; echo "\$ java -cp rf-b ReleaseFlag (JDK 27)"; "$JDK27/bin/java" -cp "$B/rf-b" ReleaseFlag 2>&1 | sed 's/^/ /'
|
|
} > "$OUT/94-release-flag.txt" 2>&1
|
|
scrub "$OUT/94-release-flag.txt"
|
|
|
|
# ---------- 95: Lombok versions against JDK 25, 26, 27 ----------
|
|
LB="$B/lombok"; mkdir -p "$LB"
|
|
for v in 1.18.34 1.18.40 1.18.46 1.18.48; do
|
|
curl -sS -m 90 -o "$LB/lombok-$v.jar" "https://repo1.maven.org/maven2/org/projectlombok/lombok/$v/lombok-$v.jar"; done
|
|
{
|
|
echo "# javac LombokProbe.java with -processorpath lombok-<version>.jar, then java LombokProbe. Class: @Getter on one field."
|
|
for v in 1.18.34 1.18.40 1.18.46 1.18.48; do for j in 25 26 27; do
|
|
rm -rf "$LB/o"; mkdir -p "$LB/o"
|
|
out="$("$(jdk $j)/bin/javac" -cp "$LB/lombok-$v.jar" -processorpath "$LB/lombok-$v.jar" -d "$LB/o" "$SRC/LombokProbe.java" 2>&1)"; rc=$?
|
|
if [ $rc -eq 0 ]; then res="compiled; $("$(jdk $j)/bin/java" -cp "$LB/o:$LB/lombok-$v.jar" LombokProbe 2>&1 | head -1)"
|
|
else res="javac failed: $(printf '%s\n' "$out" | grep -v -E '^(Note|WARNING)' | grep -m1 -E 'error|Exception' | cut -c1-150)"; fi
|
|
printf 'Lombok %-8s on JDK %s: %s\n' "$v" "$j" "$res"
|
|
done; done
|
|
echo; echo "# The same source with the jar on the class path only (no -processorpath), the way a hand-run javac used to find it:"
|
|
for j in 21 25; do rm -rf "$LB/o"; mkdir -p "$LB/o"
|
|
out="$("$(jdk $j)/bin/javac" -cp "$LB/lombok-1.18.48.jar" -d "$LB/o" "$SRC/LombokProbe.java" 2>&1)"; rc=$?
|
|
printf 'JDK %s, Lombok 1.18.48 on the class path only: exit=%s %s\n' "$j" "$rc" "$(printf '%s\n' "$out" | grep -m1 -E 'error|Note: Annotation' | cut -c1-150)"; done
|
|
for j in 23 24; do out="$(docker run --rm -v "$LB:/lb" -v "$SRC:/src:ro" "amazoncorretto:$j" javac -cp /lb/lombok-1.18.48.jar -d /tmp/o /src/LombokProbe.java 2>&1)"; rc=$?
|
|
printf 'JDK %s, Lombok 1.18.48 on the class path only: exit=%s %s\n' "$j" "$rc" "$(printf '%s\n' "$out" | grep -m1 -E 'error|Note: Annotation' | sed 's#/src/#<repo>/lanes/src/#' | cut -c1-150)"; done
|
|
} > "$OUT/95-lombok-matrix.txt" 2>&1
|
|
scrub "$OUT/95-lombok-matrix.txt"
|
|
|
|
# ---------- 96: jdeps --jdk-internals ----------
|
|
UW="$B/uw"; mkdir -p "$UW"
|
|
"$JDK25/bin/javac" -d "$UW" "$SRC/UnsafeWarning.java" >/dev/null 2>&1
|
|
{
|
|
echo "# jdeps --jdk-internals on the class from lanes/src/UnsafeWarning.java (JDK 25's jdeps)"
|
|
echo; echo "\$ jdeps --jdk-internals --multi-release 25 UnsafeWarning.class"
|
|
"$JDK25/bin/jdeps" --jdk-internals --multi-release 25 "$UW/UnsafeWarning.class" 2>&1 | sed 's/^/ /'
|
|
} > "$OUT/96-jdeps-internals.txt" 2>&1
|
|
scrub "$OUT/96-jdeps-internals.txt"
|
|
# ---------- 97: Mockito (and the ByteBuddy it brings) on 21, 25, 27 ----------
|
|
MK="$B/mockito"; mkdir -p "$MK"
|
|
for v in 5.12.0 5.17.0 5.18.0 5.23.0; do mkdir -p "$MK/$v"
|
|
cat > "$MK/$v/pom.xml" <<POM
|
|
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion><groupId>x</groupId><artifactId>x</artifactId><version>1</version>
|
|
<dependencies><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>$v</version></dependency></dependencies></project>
|
|
POM
|
|
(cd "$MK/$v" && JAVA_HOME="$JDK25" MAVEN_OPTS="$NET_JTO" mvn -q -B -ntp dependency:copy-dependencies -DoutputDirectory=lib >/dev/null 2>&1); done
|
|
{
|
|
echo "# lanes/src/MockitoProbe.java: mock an interface, stub one call. Four Mockito versions, each with the ByteBuddy it declares."
|
|
for v in 5.12.0 5.17.0 5.18.0 5.23.0; do bb="$(ls "$MK/$v/lib" | grep -E '^byte-buddy-[0-9]' | sed 's/byte-buddy-//; s/.jar//')"
|
|
for j in 21 25 27; do rm -rf "$MK/o"; mkdir -p "$MK/o"
|
|
"$(jdk $j)/bin/javac" -cp "$MK/$v/lib/*" -d "$MK/o" "$SRC/MockitoProbe.java" >/dev/null 2>&1
|
|
out="$("$(jdk $j)/bin/java" -cp "$MK/o:$MK/$v/lib/*" MockitoProbe 2>&1)"
|
|
if grep -q '^mock says hi' <<<"$out"; then res="works: mock says hi"; else res="FAILS: $(grep -m1 -E 'Mockito cannot mock' <<<"$out")"; fi
|
|
printf 'Mockito %-6s (ByteBuddy %-7s) on JDK %s: %s\n' "$v" "$bb" "$j" "$res"
|
|
done; done
|
|
echo; echo "# Notices on stderr from the working Mockito 5.23.0 on JDK 25"
|
|
rm -rf "$MK/o"; mkdir -p "$MK/o"; "$JDK25/bin/javac" -cp "$MK/5.23.0/lib/*" -d "$MK/o" "$SRC/MockitoProbe.java" >/dev/null 2>&1
|
|
"$JDK25/bin/java" -cp "$MK/o:$MK/5.23.0/lib/*" MockitoProbe 2>&1 | grep -E '^(Mockito is currently self-attaching|WARNING: A Java agent has been loaded dynamically)' | sed 's#(file:[^)]*)#(file:<path>)#' | sed 's/^/ /'
|
|
} > "$OUT/97-mockito-bytebuddy.txt" 2>&1
|
|
scrub "$OUT/97-mockito-bytebuddy.txt"
|
|
echo "done"; wc -l "$OUT"/9[2-6]-*.txt
|