java.lang.UnsupportedClassVersionError: Bad version number in .class file
(unable to load class org.shirdrn.action.FilterAction)
直接原因: .class 檔案的 Major Version 高於當前 JVM 支援的最高版本。即:編譯時 JDK 版本 > 執行時 JDK 版本。
| Major Version | JDK 版本 | 十六進位 |
|---|---|---|
| 45 | JDK 1.1 | 0x2D |
| 46 | JDK 1.2 | 0x2E |
| 47 | JDK 1.3 | 0x2F |
| 48 | JDK 1.4 | 0x30 |
| 49 | JDK 5 | 0x31 |
| 50 | JDK 6 | 0x32 |
| 51 | JDK 7 | 0x33 |
| 52 | JDK 8 | 0x34 |
| 53 | JDK 9 | 0x35 |
| 54 | JDK 10 | 0x36 |
| 55 | JDK 11 | 0x37 |
| 56 | JDK 12 | 0x38 |
| 57 | JDK 13 | 0x39 |
| 58 | JDK 14 | 0x3A |
| 59 | JDK 15 | 0x3B |
| 60 | JDK 16 | 0x3C |
| 61 | JDK 17 | 0x3D |
| 62 | JDK 18 | 0x3E |
| 63 | JDK 19 | 0x3F |
| 64 | JDK 20 | 0x40 |
| 65 | JDK 21 | 0x41 |
java -version
# 或在 Tomcat 啟動日誌首行查看
# 例:Java HotSpot(TM) 64-Bit Server VM (build 25.312-b07, mixed mode) → JDK 8u312javap -verbose target/classes/org/shirdrn/action/FilterAction.class | grep "major version"
# 或 Linux/Mac:
file target/classes/org/shirdrn/action/FilterAction.class
# 輸出:compiled Java class data, version 52.0 (Java 8)Maven 專案:
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<release>8</release> <!-- JDK 9+ 交叉編譯推薦 -->
</configuration>
</plugin>
Gradle 專案:
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType(JavaCompile) {
options.release = 8
}
setenv.sh / setenv.bat:export JAVA_HOME=/usr/lib/jvm/java-11-openjdkcatalina.sh 讀取正確 JAVA_HOMEProject → Properties → Java Compiler:勾選 Enable project specific settings,Compiler compliance level 設 1.8Installed JREs:確認指向 JDK 8 (非 JRE),且 Execution Environments 映射正確Project → Clean → Clean all projects → Maven → Update Project → Force Update在父 pom.xml 定義 pluginManagement 鎖定編譯器版本,子模組自動繼承:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<release>8</release>
</configuration>
</plugin>
</plugins>
</pluginManagement>
| 誤區 | 真相 |
|---|---|
| 「我裝了 JDK 11,為什麼還是錯?」 | Tomcat 可能仍讀舊 JAVA_HOME 或 JRE_HOME,檢查啟動日誌首行 |
| 「專案設定 1.8 還是報錯」 | 第三方依賴套件可能用更高版本編譯,需排除或升級運行時 |
「用 -target 1.8 就能在 JDK 8 跑 JDK 11 代碼」 | 錯!若代碼使用 JDK 11 API (如 var, HttpClient),編譯會失敗或運行報 NoClassDefFoundError |
| 「只改 Tomcat 版本就好」 | Tomcat 版本不決定 JVM 版本,核心在 JAVA_HOME |
#!/bin/bash
echo "=== Runtime JVM ==="
java -version 2>&1 | head -1
echo -e "\n=== Compiled Class Versions ==="
find target -name "*.class" -exec javap -verbose {} \; 2>/dev/null | grep "major version" | sort -u
echo -e "\n=== Tomcat JAVA_HOME ==="
grep -E '^JAVA_HOME|^JRE_HOME' "$CATALINA_HOME/bin/setenv.sh" 2>/dev/null || echo "未設定 setenv.sh"
UnsupportedClassVersionError 本質是「編譯版本 > 運行版本」。解決核心在於統一專案編譯目標版本與確保運行環境 JDK 版本足夠。建立團隊統一的 maven-compiler-plugin 配置規範,配合 CI/CD 檢查編譯版本,可從根源杜絕此類問題。