Fix java.lang.UnsupportedClassVersionError: Class Compiled by a More Recent Java Runtime

beginnerโ˜• Java2026-05-14| Java (JDK/JRE), Linux / macOS / Windows, any Java application or Spring Boot / Maven / Gradle project

Error Message

java.lang.UnsupportedClassVersionError: com/example/MyClass has been compiled by a more recent version of the Java Runtime
#java#version#jdk#jre

What Just Happened

You deployed a JAR, ran a class, or started a server โ€” and the JVM immediately threw:

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/example/MyClass has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0

Java stamps a version number into every compiled .class file. When the JRE loading that file is older than the JDK that compiled it, you get this error. The JVM doesn't guess โ€” it refuses to load the class entirely.

Decode the Version Numbers

The error message includes a class file version. Map it to a Java release:

  • 45.0 โ†’ Java 1
  • 52.0 โ†’ Java 8
  • 55.0 โ†’ Java 11
  • 56.0 โ†’ Java 12
  • 57.0 โ†’ Java 13
  • 58.0 โ†’ Java 14
  • 59.0 โ†’ Java 15
  • 60.0 โ†’ Java 16
  • 61.0 โ†’ Java 17
  • 62.0 โ†’ Java 18
  • 63.0 โ†’ Java 19
  • 64.0 โ†’ Java 20
  • 65.0 โ†’ Java 21

So class file version 61.0 means the class was compiled with Java 17, but the runtime only supports up to 55.0 (Java 11). Mismatch confirmed.

Diagnose: Find the Actual Versions

Check the running JRE

java -version

Example output:

openjdk version "11.0.20" 2023-07-18
OpenJDK Runtime Environment (build 11.0.20+8)
OpenJDK 64-Bit Server VM (build 11.0.20+8, mixed mode)

Check the JDK used to compile

javac -version

javac at 17, java at 11 โ€” that gap is your problem.

Inspect the class file directly

javap -verbose com/example/MyClass.class | grep "major version"

This prints the exact class file version without running the class.

On Linux: check all installed JDKs

update-alternatives --list java
# or
ls /usr/lib/jvm/

Fix Option 1 โ€” Upgrade the JRE (Recommended)

Can't recompile the JAR? That's typical with third-party libraries or CI-built artifacts. Upgrade the JRE on the target machine to match what compiled it.

Ubuntu / Debian

sudo apt install openjdk-17-jdk
sudo update-alternatives --config java

macOS (Homebrew)

brew install openjdk@17
export JAVA_HOME=$(brew --prefix openjdk@17)
export PATH="$JAVA_HOME/bin:$PATH"

Windows

Download and install the matching JDK from adoptium.net, then update JAVA_HOME and PATH in System Environment Variables.

Verify

java -version
# Should now show 17.x or higher

Fix Option 2 โ€” Recompile Targeting an Older Java Version

Own the source code? Use --release to compile down to the version your runtime supports.

Direct javac

javac --release 11 com/example/MyClass.java

Maven (pom.xml)

<properties>
  <maven.compiler.release>11</maven.compiler.release>
</properties>

Or with the compiler plugin:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.11.0</version>
  <configuration>
    <release>11</release>
  </configuration>
</plugin>

Gradle (build.gradle)

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

Gradle 6.7+ introduced toolchains โ€” the cleaner way to lock the version:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

Spring Boot projects

# application.properties or pom.xml property
<java.version>11</java.version>

Then rebuild:

./mvnw clean package
# or
./gradlew build

Fix Option 3 โ€” Point to the Correct JVM at Runtime

Multiple JDKs installed? Skip the system default entirely and pass the full path:

/usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar myapp.jar

Or set JAVA_HOME before running:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
java -jar myapp.jar

Handy in CI/CD pipelines or Docker containers where you don't want to touch system defaults.

Common Scenario: Docker Container with Wrong Base Image

Containerized apps hit this constantly. The Dockerfile uses openjdk:11 to run a JAR compiled with Java 17 โ€” the versions never matched to begin with.

# Wrong
FROM openjdk:11-jre-slim
COPY target/myapp.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
# Correct โ€” match the compile target
FROM eclipse-temurin:17-jre-alpine
COPY target/myapp.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

Verification Steps

  • Confirm the JRE version matches or exceeds the compile target:``` java -version
  - Recompiled? Check the new class file version:```
javap -verbose target/classes/com/example/MyClass.class | grep "major version"
  • Run the application โ€” no UnsupportedClassVersionError means you're done:``` java -jar target/myapp.jar
  - For Docker: rebuild and run the container, check startup logs.

## Lessons Learned

  - **Pin Java versions in CI/CD.** Pipeline compiles with Java 21, production runs Java 11 โ€” this error hits every single deploy. Lock both to the same version and don't let them drift.
  - **Use `--release` over `-source`/`-target`.** The old flags only set the bytecode version. They won't stop you from calling Java 17 APIs that don't exist in Java 11. `--release` enforces both the bytecode version and API availability.
  - **Check third-party JARs.** The error doesn't always point to your code. Run `javap -verbose` on the class named in the stack trace to identify which dependency it came from, then check that library's minimum Java requirement.
  - **Gradle toolchains and Maven wrapper eliminate the "works on my machine" problem.** They guarantee the build uses the declared Java version, regardless of what's installed locally.

Related Error Notes