Javaの開発や運用において、実行時に突然java.lang.UnsupportedClassVersionErrorが発生し、プログラムが停止してしまうことがあります。
このエラーは、Javaの実行環境(JRE/JVM)と、プログラムがビルドされた際のコンパイラ(JDK)のバージョンが一致していないことを示しています。
特に近年ではJavaのリリースサイクルが早まり、プロジェクトごとに異なるLTS(Long Term Support)バージョンを使い分ける機会が増えたため、このエラーに直面するエンジニアが増えています。
本記事では、このエラーが発生する根本的なメカニズムから、具体的な確認方法、そして開発環境やビルドツールにおける解決策までを詳しく解説します。
java.lang.UnsupportedClassVersionErrorとは何か
java.lang.UnsupportedClassVersionErrorは、Java仮想マシン(JVM)がクラスファイルをロードしようとした際に、そのクラスファイルのバージョンがJVMのサポートしているバージョンよりも新しい場合にスローされるエラーです。
Javaのプログラムは、ソースコード(.javaファイル)をコンパイルしてバイトコード(.classファイル)に変換します。
このクラスファイルの中には「メジャーバージョン」と呼ばれる数値が記録されており、JVMはこの数値を参照して、自分が実行可能な形式かどうかを判断します。
JVMには「自分より古いバージョンでコンパイルされたファイルは実行できるが、自分より新しいバージョンでコンパイルされたファイルは実行できない」という後方互換性の原則があります。
したがって、例えばJDK 21でコンパイルされたクラスファイルを、Java 17のランタイムで実行しようとすると、このエラーが発生します。
逆に、Java 11でコンパイルされたものをJava 21で動かすことは問題ありません。
エラーメッセージの読み解き方
エラーが発生した際、コンソールには以下のようなメッセージが表示されることが一般的です。
java.lang.UnsupportedClassVersionError: com/example/Main 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
このメッセージには解決のための重要なヒントが隠されています。
class file version 65.0:これはクラスファイルがJava 21でコンパイルされたことを示しています。only recognizes class file versions up to 61.0:これは現在の実行環境がJava 17までしか対応していないことを示しています。
このように、エラーメッセージに表示される数値をJavaのバージョンに変換することで、どのバージョンの不一致が起きているかを正確に把握できます。
Javaバージョンとクラスファイルバージョンの対応表
Javaのメジャーバージョンと、それに対応するクラスファイルのバージョン番号の対応は以下の通りです。
トラブルシューティングの際の参照用として活用してください。
| Javaバージョン | クラスファイル形式(メジャーバージョン) |
|---|---|
| Java SE 23 | 67 |
| Java SE 22 | 66 |
| Java SE 21 (LTS) | 65 |
| Java SE 20 | 64 |
| Java SE 19 | 63 |
| Java SE 18 | 62 |
| Java SE 17 (LTS) | 61 |
| Java SE 11 (LTS) | 55 |
| Java SE 8 (LTS) | 52 |
| Java SE 7 | 51 |
注意点として、Java 8以降は「メジャーバージョン = Javaバージョン + 44」という計算式で求めることができます。
例えば、Java 21であれば 21 + 44 = 65 となります。
エラーが発生する主な原因
このエラーが発生するシナリオは、主に以下の3つのパターンに集約されます。
1. 環境変数の設定ミス
開発機に複数のJDKをインストールしている場合、コンパイル時に使用する javac のパスと、実行時に使用する java コマンドのパスが異なるバージョンのJDK/JREを指していることがあります。
例えば、PATH 環境変数の優先順位により、コンパイルは最新のJDKで行われ、実行は古いOS標準のJavaで行われるといったケースです。
2. IDE(統合開発環境)の設定不備
IntelliJ IDEAやEclipse、Visual Studio CodeなどのIDEでは、プロジェクトごとに「プロジェクトSDK」や「言語レベル」を設定します。
プロジェクトのビルド設定では高いバージョンを指定しているにもかかわらず、IDE内で設定されている実行用JREが古い場合にエラーが発生します。
3. ビルドツールと実行環境の乖離
MavenやGradleを使用してビルドを行い、成果物(JARファイルなど)をサーバーへデプロイした際に発生します。
ビルドサーバー(CI/CD)では最新のJDKを使用しているが、デプロイ先のデリバリー環境や本番サーバーのJavaバージョンが古いまま更新されていないという状況です。
具体的な解決策と修正手順
原因を特定したら、以下の手順で修正を行います。
状況に合わせて最適な方法を選択してください。
手順1:現在のバージョンを確認する
まずは、現在使用しているコンパイラとランタイムのバージョンをターミナル(コマンドプロンプト)で確認します。
# コンパイラのバージョン確認
javac -version
# 実行環境のバージョン確認
java -version
もし javac が 21.x.x で、 java が 17.x.x であれば、実行環境をアップグレードするか、コンパイルターゲットを下げる必要があります。
手順2:実行環境(JRE/JDK)をアップグレードする
最も推奨される解決策は、実行環境をコンパイル環境と同じか、それ以上のバージョンに合わせることです。
Windowsの場合、JAVA_HOME 環境変数を新しいJDKのインストールディレクトリに変更し、PATH 変数の先頭に %JAVA_HOME%\bin を追加します。
macOSやLinuxの場合は、sdkman などのバージョン管理ツールを使用すると切り替えがスムーズです。
# SDKMAN! を使用した例
sdk install java 21.0.2-tem
sdk use java 21.0.2-tem
手順3:コンパイル時のターゲットバージョンを下げる
実行環境のバージョンを上げられない事情がある場合(古いサーバーでの運用など)、コンパイル時に出力されるクラスファイルのバージョンを下げることができます。
javacコマンドを使用する場合
--release オプション(Java 9以降)を使用します。
# Java 17互換のクラスファイルを作成する
javac --release 17 Main.java
Mavenを使用する場合
pom.xml の maven-compiler-plugin 設定を修正します。
<project>
<properties>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<!-- ターゲットとなるバージョンを指定 -->
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
</project>
Gradleを使用する場合
build.gradle に以下の設定を追加します。
java {
// ターゲットバージョンを指定
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
手順4:IDEの設定を見直す(IntelliJ IDEAの例)
IDEを使用している場合は、以下の設定箇所が一致しているか確認してください。
- Project Structure > Project
SDKとLanguage levelが一致しているか。- Settings > Build, Execution, Deployment > Compiler > Java Compiler
各モジュールの
Target bytecode versionが適切か。- Run/Debug Configurations
実行時に使用される
JREが正しいか。
動作確認用のサンプルプログラム
実際にエラーを発生させ、解決を確認するための簡単なコードを紹介します。
// Main.java
public class Main {
public static void main(String[] args) {
// Java 21の新しい文字列メソッドなどを使ってみる
String message = " Hello, Java Version Check! ";
System.out.println(message.strip());
// ランタイムのバージョンを表示
System.out.println("Runtime Version: " + System.getProperty("java.version"));
}
}
このファイルをJDK 21でコンパイルし、Java 17で実行するとエラーが再現されます。
# JDK 21でコンパイル
/path/to/jdk-21/bin/javac Main.java
# Java 17で実行(エラー発生)
/path/to/jdk-17/bin/java Main
出力結果(エラー時):
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: Main 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
次に、ターゲットを指定してコンパイルし直します。
# ターゲットを17に指定してコンパイル
javac --release 17 Main.java
# 再度Java 17で実行(成功)
/path/to/jdk-17/bin/java Main
出力結果(成功時):
Hello, Java Version Check!
Runtime Version: 17.0.x
再発を防止するためのベストプラクティス
このエラーを未然に防ぐために、以下の運用ルールを導入することを検討してください。
- Dockerによる環境の固定化
開発環境、CI環境、本番環境をすべて同じDockerイメージベースで構築することで、Javaバージョンの不一致を完全に排除できます。
Dockerfile内でベースイメージ(例:eclipse-temurin:21-jdk)を指定すれば、環境差異による問題は発生しません。- ビルドツールのToolchains機能の活用
MavenやGradleには「Toolchains」という機能があります。
これを利用すると、ローカルの環境変数に依存せず、ビルドスクリプト内で定義された特定のJDKバージョンを自動的にダウンロード・使用してビルドを行うことができます。
- .java-version ファイルの設置
sdkmanやasdfなどのツールを利用している場合、プロジェクトのルートに.java-versionファイルを置いておくと、ディレクトリを移動するだけで自動的にJavaバージョンが切り替わります。
まとめ
java.lang.UnsupportedClassVersionError は、一見複雑に見えるかもしれませんが、その本質は「コンパイル時よりも古いJavaで実行しようとしている」という単純な不一致です。
解決のためには、まずエラーメッセージに含まれるクラスファイルバージョン(65.0、61.0など)を確認し、どのバージョンの差分があるかを特定しましょう。
その上で、実行環境をアップデートするか、ビルド時のターゲットバージョンを適切に設定することで解決が可能です。
特にクラウドネイティブな開発が主流となっている現代では、CI/CDパイプラインやコンテナオーケストレーションにおけるJavaバージョンの管理が重要です。
本記事で紹介した対応表や設定方法を活用し、スムーズなトラブルシューティングと安定したアプリケーション運用を実現してください。






