Skip to content

feat(build): bump to Java 25 and verify Spigot 1.21–26.2 compatibility - #175

Merged
imDMK merged 1 commit into
mainfrom
feat/java-25-spigot-compat
Aug 26, 2026
Merged

feat(build): bump to Java 25 and verify Spigot 1.21–26.2 compatibility#175
imDMK merged 1 commit into
mainfrom
feat/java-25-spigot-compat

Conversation

@imDMK

@imDMK imDMK commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Raise the toolchain and bytecode target to Java 25, and apply the compiler options to every JavaCompile task instead of only compileJava, so test compilation no longer targets a different release than production code.

The plugin is built against the newest Spigot API while advertising api-version 1.21, which had silently drifted out of compatibility:

  • Sound#getKeyOrThrow() and Enchantment#getKeyOrThrow() come from org.bukkit.registry.RegistryAware, a type that does not exist on 1.21.
  • Falling back to getKey() alone is not enough either — org.bukkit.Sound was an enum back then and is an interface today, so compiling against the new API emits invokeinterface and 1.21 throws IncompatibleClassChangeError.

Read the key through org.bukkit.Keyed, an interface in every supported version, so the emitted call site resolves on both ends of the range.

Two verification tasks now run as part of check, in every module:

  • compileJavaSpigotMin recompiles the sources against the oldest supported API and catches newer-only symbols.
  • checkSpigotBinaryCompatibility scans the emitted org/bukkit call sites with ASM and reports unresolved members as well as invokeinterface / invokevirtual mismatches, which the source compile cannot see.

Raise the toolchain and bytecode target to Java 25, and apply the compiler
options to every JavaCompile task instead of only compileJava, so test
compilation no longer targets a different release than production code.

The plugin is built against the newest Spigot API while advertising
api-version 1.21, which had silently drifted out of compatibility:

  * Sound#getKeyOrThrow() and Enchantment#getKeyOrThrow() come from
    org.bukkit.registry.RegistryAware, a type that does not exist on 1.21.
  * Falling back to getKey() alone is not enough either — org.bukkit.Sound
    was an enum back then and is an interface today, so compiling against
    the new API emits invokeinterface and 1.21 throws
    IncompatibleClassChangeError.

Read the key through org.bukkit.Keyed, an interface in every supported
version, so the emitted call site resolves on both ends of the range.

Two verification tasks now run as part of check, in every module:

  * compileJavaSpigotMin recompiles the sources against the oldest
    supported API and catches newer-only symbols.
  * checkSpigotBinaryCompatibility scans the emitted org/bukkit call sites
    with ASM and reports unresolved members as well as invokeinterface /
    invokevirtual mismatches, which the source compile cannot see.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@imDMK
imDMK merged commit d5132ab into main Aug 26, 2026
1 check passed
@imDMK
imDMK deleted the feat/java-25-spigot-compat branch August 26, 2026 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant