14.

UnsupportedClassVersionError「class file version 61.0」の原因と対処

編集
この記事の要点
  • コンパイル時 JDK のバージョン > 実行時 JRE のバージョンでこのエラーが出る
  • メッセージ has been compiled by a more recent version of the Java Runtime + class file version 61.0
  • major version: 52=Java 8 / 55=Java 11 / 61=Java 17 / 65=Java 21
  • 対処: ① 実行 JRE を上げる、② コンパイル時のターゲットを下げる(--release / -source -target
  • Maven: maven.compiler.release、Gradle: sourceCompatibility / targetCompatibility
  • 配布用 jar は古い Java 互換でビルドするのが安全(LTS = 8 / 11 / 17 / 21)

このエラーの典型

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 versionJava バージョンLTS
52.0Java 8
53.0Java 9×
54.0Java 10×
55.0Java 11
56.0Java 12×
57.0Java 13×
58.0Java 14×
59.0Java 15×
60.0Java 16×
61.0Java 17
62.0Java 18×
63.0Java 19×
64.0Java 20×
65.0Java 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 IDEAFile → Project Structure → Project SDK / Language level / Modules → Sources の Language level
EclipseWindow → Preferences → Java → Compiler → Compiler compliance level、+ プロジェクト Properties → Java Compiler
VS Codejava.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 に。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. java.lang.IllegalStateException: CGLIB is required to process @Configuration classes
  2. Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
  3. No mapping found for HTTP request with URI ... in DispatcherServlet with name ...
  4. An internal error occurred during: "Building UI model". com/google/common/base/Function
  5. No identifier specified for entity : ...
  6. org.hibernate.hql.internal.ast.QuerySyntaxException: table_name is not mapped
  7. No compiler is provided in this environment
  8. java.sql.SQLException: The server time zone value ' ... ' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone
  9. Caused by: java.lang.RuntimeException: Executing an update/delete query
  10. Not supported for DML operations
  11. Field ... required a bean of type ... hat could not be found.
  12. Annotation-specified bean name ' ... ' for bean class [ ... ] conflicts with existing, non-compatible bean definition of same name and class [...]
  13. Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.
  14. Exception in thread "main" java.lang.UnsupportedClassVersionError