Sửa lỗi java.lang.UnsupportedClassVersionError: Class được biên dịch bởi Java Runtime mới hơn

beginner Java2026-05-14| Java (JDK/JRE), Linux / macOS / Windows, mọi ứng dụng Java hoặc dự án Spring Boot / Maven / Gradle

Error Message

java.lang.UnsupportedClassVersionError: com/example/MyClass has been compiled by a more recent version of the Java Runtime
#java#version#jdk#jre

Chuyện Gì Vừa Xảy Ra

Bạn deploy một JAR, chạy một class, hoặc khởi động server — và JVM lập tức ném ra lỗi:

Exception in thread "main" java.lang.UnsupportedClassVersionError: com/example/MyClass 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

Java ghi một số phiên bản vào mỗi file .class đã biên dịch. Khi JRE tải file đó cũ hơn JDK đã biên dịch nó, bạn sẽ gặp lỗi này. JVM không đoán mò — nó từ chối tải class hoàn toàn.

Giải Mã Các Số Phiên Bản

Thông báo lỗi chứa một phiên bản class file. Tra cứu tương ứng với phiên bản Java:

  • 45.0 → Java 1
  • 52.0 → Java 8
  • 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

Vậy class file version 61.0 có nghĩa là class được biên dịch bằng Java 17, nhưng runtime chỉ hỗ trợ đến 55.0 (Java 11). Xác nhận không tương thích.

Chẩn Đoán: Tìm Phiên Bản Thực Tế

Kiểm tra JRE đang chạy

java -version

Ví dụ đầu ra:

openjdk version "11.0.20" 2023-07-18
OpenJDK Runtime Environment (build 11.0.20+8)
OpenJDK 64-Bit Server VM (build 11.0.20+8, mixed mode)

Kiểm tra JDK dùng để biên dịch

javac -version

javac ở phiên bản 17, java ở phiên bản 11 — khoảng cách đó chính là vấn đề của bạn.

Kiểm tra trực tiếp file class

javap -verbose com/example/MyClass.class | grep "major version"

Lệnh này in ra phiên bản class file chính xác mà không cần chạy class.

Trên Linux: kiểm tra tất cả JDK đã cài

update-alternatives --list java
# hoặc
ls /usr/lib/jvm/

Cách Sửa 1 — Nâng Cấp JRE (Khuyến Nghị)

Không thể biên dịch lại JAR? Điều này thường gặp với thư viện bên thứ ba hoặc artifact được build từ CI. Hãy nâng cấp JRE trên máy đích để khớp với phiên bản đã biên dịch.

Ubuntu / Debian

sudo apt install openjdk-17-jdk
sudo update-alternatives --config java

macOS (Homebrew)

brew install openjdk@17
export JAVA_HOME=$(brew --prefix openjdk@17)
export PATH="$JAVA_HOME/bin:$PATH"

Windows

Tải và cài đặt JDK phù hợp từ adoptium.net, sau đó cập nhật JAVA_HOMEPATH trong System Environment Variables.

Xác Nhận

java -version
# Bây giờ nên hiển thị 17.x hoặc cao hơn

Cách Sửa 2 — Biên Dịch Lại Nhắm Đến Phiên Bản Java Cũ Hơn

Bạn có mã nguồn? Dùng --release để biên dịch xuống phiên bản runtime của bạn hỗ trợ.

Dùng javac trực tiếp

javac --release 11 com/example/MyClass.java

Maven (pom.xml)

<properties>
  <maven.compiler.release>11</maven.compiler.release>
</properties>

Hoặc dùng compiler plugin:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.11.0</version>
  <configuration>
    <release>11</release>
  </configuration>
</plugin>

Gradle (build.gradle)

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

Gradle 6.7+ giới thiệu toolchains — cách sạch hơn để khóa phiên bản:

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)
    }
}

Dự án Spring Boot

# application.properties hoặc thuộc tính pom.xml
<java.version>11</java.version>

Sau đó build lại:

./mvnw clean package
# hoặc
./gradlew build

Cách Sửa 3 — Trỏ Đến JVM Đúng Khi Chạy

Đã cài nhiều JDK? Bỏ qua mặc định hệ thống và truyền đường dẫn đầy đủ:

/usr/lib/jvm/java-17-openjdk-amd64/bin/java -jar myapp.jar

Hoặc đặt JAVA_HOME trước khi chạy:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
java -jar myapp.jar

Rất tiện trong CI/CD pipeline hoặc Docker container khi bạn không muốn động đến cài đặt mặc định của hệ thống.

Tình Huống Thường Gặp: Docker Container Dùng Base Image Sai

Ứng dụng đóng gói container gặp lỗi này liên tục. Dockerfile dùng openjdk:11 để chạy JAR được biên dịch bằng Java 17 — các phiên bản không bao giờ khớp ngay từ đầu.

# Sai
FROM openjdk:11-jre-slim
COPY target/myapp.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
# Đúng — khớp với target biên dịch
FROM eclipse-temurin:17-jre-alpine
COPY target/myapp.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

Các Bước Xác Nhận

  • Xác nhận phiên bản JRE khớp hoặc cao hơn target biên dịch:``` java -version
  - Đã biên dịch lại? Kiểm tra phiên bản class file mới:```
javap -verbose target/classes/com/example/MyClass.class | grep "major version"
  • Chạy ứng dụng — không có UnsupportedClassVersionError là xong:``` java -jar target/myapp.jar
  - Với Docker: build lại và chạy container, kiểm tra log khởi động.

## Bài Học Rút Ra

  - **Cố định phiên bản Java trong CI/CD.** Pipeline biên dịch bằng Java 21, production chạy Java 11 — lỗi này xuất hiện mỗi lần deploy. Khóa cả hai về cùng phiên bản và đừng để chúng lệch nhau.
  - **Dùng `--release` thay vì `-source`/`-target`.** Các flag cũ chỉ đặt phiên bản bytecode. Chúng không ngăn bạn gọi các API Java 17 không tồn tại trong Java 11. `--release` áp dụng cả phiên bản bytecode lẫn tính khả dụng của API.
  - **Kiểm tra JAR bên thứ ba.** Lỗi không phải lúc nào cũng chỉ vào code của bạn. Chạy `javap -verbose` trên class được đề cập trong stack trace để xác định dependency nào gây ra, sau đó kiểm tra yêu cầu Java tối thiểu của thư viện đó.
  - **Gradle toolchains và Maven wrapper loại bỏ vấn đề "chạy được trên máy tôi".** Chúng đảm bảo build sử dụng đúng phiên bản Java đã khai báo, bất kể máy cài gì.

Related Error Notes