Java「Unsupported Class Version Error(class file version)」の原因と直し方
UnsupportedClassVersionError(class file version)は、実行側の JVM を上げるか --release を下げれば直る。
実行側の JVM がビルドした Java より古いと出る。
公開: 更新:
/usr/lib/jvm/java-17-openjdk-amd64/bin/java App Error: LinkageError occurred while loading main class App java.lang.UnsupportedClassVersionError: App has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0
/usr/lib/jvm/java-17-openjdk-amd64/bin/java App Hello from Java 17
2026-10-17 に eclipse-temurin:21-jdk(Java 21.0.12.1) で実際に打って取った出力。検証環境の詳細
要約
UnsupportedClassVersionError は、クラスファイルの形式バージョンが実行側の JVM の対応範囲を超えているときに出る。
コードの誤りではなく、ビルドした Java と実行している Java の食い違いである。
Error: LinkageError occurred while loading main class com.example.App
java.lang.UnsupportedClassVersionError: com/example/App 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この例では「61.0 のクラスを 55.0 までしか読めない JVM で動かした」と言っている。
まず数値を Java のバージョンに読み替える。
実行例
JDK 21 でコンパイルした App.class(class file version 65)を Java 17 の JVM で動かすと、61.0 までしか読めないという UnsupportedClassVersionError で終了コード 1 になった。
実行側を Java 21 にするか、javac --release 17 で出力側を下げると、同じ Java 17 の JVM でも通った。
Java 17 に無い List.reversed() は、--release 17 がコンパイル時に弾いた。
$ javac App.java
$ echo $?
0$ /usr/lib/jvm/java-17-openjdk-amd64/bin/java App
Error: LinkageError occurred while loading main class App
java.lang.UnsupportedClassVersionError: App has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0
$ echo $?
1$ javac -version
javac 21.0.12.1$ /usr/lib/jvm/java-17-openjdk-amd64/bin/java -version
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-26.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-26.04-Ubuntu, mixed mode, sharing)$ javap -v App.class | grep 'major version'
major version: 65$ java App
Hello from Java 21
$ echo $?
0$ javac --release 17 App.java
$ echo $?
0$ javap -v App.class | grep 'major version'
major version: 61$ /usr/lib/jvm/java-17-openjdk-amd64/bin/java App
Hello from Java 17
$ echo $?
0$ javac --release 17 Newer.java
Newer.java:3: error: cannot find symbol
System.out.println(java.util.List.of(1, 2, 3).reversed());
^
symbol: method reversed()
location: interface List<Integer>
1 error
$ echo $?
1— 2026-10-17 時点の出力
検証環境Java 21.0.12.1 / 2026-10-17 検証
- 検証日
- 実行環境
eclipse-temurin:21-jdkUbuntu 26.04.1 LTS- バージョン
- Java 21.0.12.1
この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。
解決策
1. 数値を Java のバージョンに読み替える
主な対応は次のとおりで、JVM 仕様書の class File Format(新しいタブで開く) に一覧がある。
52 → Java 8
55 → Java 11
59 → Java 15
61 → Java 17
65 → Java 212. 実行側の JVM を上げる
java -version
javac -version # この2つが食い違っていないかを最初に見る数値が示す Java 版以上の JVM を用意すれば、それだけで解消する。
3. 上げられないなら出力側を下げる
javac --release 11 -d out src/com/example/App.java--release は形式バージョンだけでなく、その版に存在しない標準 API の使用もコンパイル時に弾く。
古い -source / -target の組み合わせでは API の互換までは見てくれないため、--release を使うほうが安全である。
4. 原因の jar を特定する
エラーに出るクラス名が自分のコードでなければ、依存側が原因である。
バージョン表記からビルドに使われた Java 版を逆算し、そのライブラリを実行環境に合う版へ落とす。
よくある原因
- ビルドと実行で JDK が違う。
手元は最新 JDK、サーバやコンテナは古い JRE という組み合わせが典型である。 JAVA_HOMEと IDE の実行構成がずれている。
ターミナルでは通るのに IDE から実行すると落ちるか、その逆になる。- 依存 jar だけが新しい。
自分のコードは古い形式でも、ロードされるライブラリが新しければそこで落ちる。
クラス名がライブラリ側のものになっていれば、原因を特定しやすい。 - CI でセットアップした Java が、ビルドツールの設定と違う。
ツールチェーンで 17 を指定しているのに、実行ステップは 11 のままというケースがある。