← Debugging Guides

阅读中文版本

Java invalid target release — Wrong JDK or Compiler Flag

Fix "invalid target release: N" by installing the matching JDK, aligning maven.compiler.release, and checking JAVA_HOME.

intermediatedebuggingjavabuildjdk

Symptoms

  • Compilation fails with "invalid target release: 17"
  • The build works on one machine and fails on CI
  • Maven or Gradle reports the target version while java -version shows another

Possible causes

  • The compiler runs on an older JDK than the requested target release
  • maven.compiler.release or sourceCompatibility exceeds the installed JDK
  • JAVA_HOME points at a different JDK than the one on PATH

Diagnosis steps

Compare compiler JDK with target release

mvn -version && javac -version && echo "$JAVA_HOME"

Interpretation

The runtime JDK must be at least the requested release; a mismatch produces invalid target release.

Check configured release

grep -rn "release>\|source>\|target>\|compiler.release" pom.xml build.gradle

Interpretation

The configured release tells you which JDK to install or which value to lower.

Root cause

javac cannot produce bytecode targeting a release newer than the JDK performing compilation. Requesting release 17 from a JDK 11 toolchain therefore fails with invalid target release before any class is emitted.

Fix

Install and select the matching JDK (set JAVA_HOME and PATH), align maven.compiler.release/sourceCompatibility with the available JDK, or use toolchains to pin the compiler JDK independently of the runtime.

Risk note

Lowering the target to match an old JDK may ship bytecode lacking features and missed security fixes; prefer installing the correct JDK.

Verify the fix

Rebuild and confirm compilation succeeds; check the produced class file version matches the intended release with javap -v.

Symptoms

This guide profiles the failure behind “Java invalid target release — Wrong JDK or Compiler Flag”. It walks through the observable symptoms, a reproducible diagnosis path, the underlying root cause, the concrete fix, and how to verify the change and prevent a regression.

Observed symptoms include:

  • Compilation fails with “invalid target release: 17”
  • The build works on one machine and fails on CI
  • Maven or Gradle reports the target version while java -version shows another

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Compare compiler JDK with target release

mvn -version && javac -version && echo "$JAVA_HOME"

The runtime JDK must be at least the requested release; a mismatch produces invalid target release.

Step 2: Check configured release

grep -rn "release>\|source>\|target>\|compiler.release" pom.xml build.gradle

The configured release tells you which JDK to install or which value to lower.

Likely contributors, in order of frequency:

  • The compiler runs on an older JDK than the requested target release
  • maven.compiler.release or sourceCompatibility exceeds the installed JDK
  • JAVA_HOME points at a different JDK than the one on PATH

Root Cause

javac cannot produce bytecode targeting a release newer than the JDK performing compilation. Requesting release 17 from a JDK 11 toolchain therefore fails with invalid target release before any class is emitted.

The Fix

Install and select the matching JDK (set JAVA_HOME and PATH), align maven.compiler.release/sourceCompatibility with the available JDK, or use toolchains to pin the compiler JDK independently of the runtime.

Watch out: Lowering the target to match an old JDK may ship bytecode lacking features and missed security fixes; prefer installing the correct JDK.

<!-- Maven toolchains: compile with JDK 17 regardless of runtime -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.13.0</version>
  <configuration>
    <release>17</release>
  </configuration>
</plugin>

# verify the bytecode version
javap -v target/classes/com/example/Main.class | grep 'major version'

Verify and Prevent

Rebuild and confirm compilation succeeds; check the produced class file version matches the intended release with javap -v.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.