タイトル: Exception in thread "main" java.lang.UnsupportedClassVersionError
SEOタイトル: UnsupportedClassVersionError「class file version 61.0」の原因と対処
| この記事の要点 |
|
このエラーの典型
Exception in thread "main" 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 52.0
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
...
意味: 「このクラスファイルは Java 17 でコンパイルされている (61.0) が、実行している JRE は Java 8 (52.0) までしか読めません」。
class file version 対応表
| major version | Java バージョン | LTS |
|---|---|---|
| 52.0 | Java 8 | ○ |
| 53.0 | Java 9 | × |
| 54.0 | Java 10 | × |
| 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 | ○ |
原因の確認
# 実行時 Java バージョン
java -version
# openjdk version "1.8.0_362" ← Java 8
# コンパイル時 Java バージョン
javac -version
# javac 17.0.5 ← Java 17
# クラスファイルの version を直接見る
javap -v App.class | grep "major version"
# major version: 61
# または file コマンド
file App.class
# App.class: compiled Java class data, version 61.0 (Java SE 17)
対処 1: 実行時 JRE を上げる
最も素直な解決。サーバの JRE を最新 LTS に上げます:
# CentOS / RHEL
sudo yum install java-17-openjdk
# Ubuntu / Debian
sudo apt install openjdk-17-jre
# 複数バージョン共存時は alternatives で切替
sudo alternatives --config java
# macOS (Homebrew)
brew install openjdk@17
# 環境変数
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$JAVA_HOME/bin:$PATH
対処 2: コンパイル時のターゲットを下げる
サーバ JRE を上げられない場合(古い環境への配布等)はコンパイル側を合わせます:
# Java 11 で動かしたい場合 (Java 17 でコンパイル中)
# --release 推奨 (Java 9+)
javac --release 11 App.java
# 古い書き方
javac -source 11 -target 11 -bootclasspath /path/to/jdk11/jre/lib/rt.jar App.java
Maven の設定
11
11
11
maven-compiler-plugin
3.11.0
11
Gradle の設定
// build.gradle
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
// または toolchain (Gradle 6.7+, 推奨)
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
// Kotlin DSL (build.gradle.kts)
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
tasks.withType {
options.release.set(11)
}
IDE での設定確認
| IDE | 確認場所 |
|---|---|
| IntelliJ IDEA | File → Project Structure → Project SDK / Language level / Modules → Sources の Language level |
| Eclipse | Window → Preferences → Java → Compiler → Compiler compliance level、+ プロジェクト Properties → Java Compiler |
| VS Code | java.configuration.runtimes + java.compile.nullAnalysis.mode 設定 |
Tomcat / アプリサーバで起きた場合
Tomcat 自体が古い Java で動いていると、WAR 内の Java 17 クラスを読めずに 500 エラーになります:
# Tomcat が使う Java を確認
ps -ef | grep tomcat
# /usr/lib/jvm/java-8-openjdk/bin/java ... org.apache.catalina.startup.Bootstrap
# CATALINA_HOME/bin/setenv.sh で明示
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
export PATH=$JAVA_HOME/bin:$PATH
# Tomcat 再起動
systemctl restart tomcat
FAQ
Q: 依存ライブラリの jar が新しい Java でコンパイルされていて読めない
A: ライブラリの古いバージョンを使うか、自分のアプリも合わせて Java を上げる以外にありません。
Q: --release 8 と -source 8 -target 8 の違い
A: --release は API も Java 8 に縛る(新 API 呼び出しがコンパイルエラーになる)。-source -target は bytecode だけ古くする(実行時 NoSuchMethodError の危険)。
Q: Android で起きた
A: Android Gradle Plugin の compileOptions.sourceCompatibility / targetCompatibility を Java 8 / 11 に。