Skip to content

/compat/java/class-file-version-by-java-release

Java class file major version by release: 52 is Java 8, 61 is 17, 65 is 21

verified onenvironmentlocal · linux 6.18.44-fc-v185 x64 · GNU bash 5.2.21 · openjdk version "21.0.12.1" 2026-08-18updated
tool
Java
versions
Java 8, Java 11, Java 17, Java 21
os
any

Every .class file starts with a major version number that records the Java release that wrote it: 52 for Java 8, 55 for Java 11, 61 for Java 17 and 65 for Java 21. A JVM runs a class file only if its major version is not newer than the highest one that JVM knows, so code compiled by Java 21 cannot run on Java 17.

Version table

From Java 2 on the number is the release number plus 44. Java 5 is 49 and Java 8 is 52.

Java releaseMajor versionNotes
852LTS. The oldest release that JDK 21 can still target with --release.
953Introduced modules, and the --release option.
1155LTS.
1761LTS.
1862
1963
2064
2165LTS. A class compiled with preview features enabled also records a minor version of 65535, which only the same release can run.

For releases 10, 12 to 16 and others the same rule applies: release plus 44.

What works with what

Class compiled forRuns on an older JVM?Runs on a newer JVM?
Java 8 (52)Only on Java 8 or newerYes, on every later JVM
Java 11 (55)No on Java 8, yes on 11 or newerYes
Java 17 (61)No on Java 8 and 11, yes on 17 or newerYes
Java 21 (65)No on Java 17 or olderYes, on 21 and later

The rule is one-directional: backward compatibility is the platform's goal, but nothing runs on a JVM older than the one that wrote the class. The failure is java.lang.UnsupportedClassVersionError: ... has been compiled by a more recent version of the Java Runtime; see UnsupportedClassVersionError.

Check it on your machine

The block compiles one class for three releases and prints the major version that javap finds. It also shows what javac says for releases it no longer supports. JAVA_TOOL_OPTIONS is unset so no "Picked up" line is printed.

bash
unset JAVA_TOOL_OPTIONS
cat > Hello.java <<'JAVA'
public class Hello {
    public static void main(String[] args) {
        System.out.println("hi");
    }
}
JAVA
for r in 11 17 21; do
  rm -f Hello.class
  javac --release $r Hello.java
  printf "release $r: "
  javap -v Hello.class | grep "major version"
done
echo "--- unsupported release"
javac --release 7 Hello.java 2>&1 | head -1

Output

release 11:   major version: 55
release 17:   major version: 61
release 21:   major version: 65
--- unsupported release
error: release version 7 not supported

The output follows the table: 55, 61 and 65. Release 7 is refused by this JDK, because each JDK keeps only a window of older targets (the number depends on the JDK version you use).

Choosing a target

  • Libraries: compile for the oldest release your users still run, with --release. Compiling on a new JDK without it produces class files only that JDK or newer can load.
  • Applications: compile for the runtime you deploy. A mismatch between the build JDK and the runtime JRE is the usual cause of the version error.
  • Maven and Gradle: set maven.compiler.release or the Gradle options.release property so the same rule applies in the build tool. See javac --release.

Why --release and not --target

--target only writes the class file version. --release N also limits the code to the public API of release N, so a call to a method added in a later release fails at compile time instead of failing at run time with NoSuchMethodError on the older JVM.

Compiled classes are found through the classpath, and a JAR can mix class versions, so the check above is per class, not per JAR.

FAQ

Can a newer JVM run classes compiled for an older Java release?

Yes. A JVM runs class files whose major version is up to its own and down to the oldest it still supports, so Java 21 runs classes compiled for Java 8. The reverse fails: an older JVM rejects a newer major version with UnsupportedClassVersionError.

How do I compile for an older Java version?

Use javac --release N, for example javac --release 17. It sets the class file version and also restricts the code to the language features and standard library API of release N. The older -source and -target options only change the language level and the version, not the API.

How do I find the Java version a class file was compiled for?

Run javap -v ClassName and read the major version line. Subtract 44 from the number to get the Java release for versions 9 and later, so 61 is Java 17. The file command also prints the version on Linux and macOS.

Sources