一、问题
用maven对一个开源项目打包时,遇到了“错误的类文件: *** 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中。”:
二、原因
原因是当前java环境是Java 8(版本52.0),但项目中依赖的某个类文件(比如上面的的org.eclipse.core.runtime.Plugin)是由Java 17(版本61.0)编译生成的,Java运行时环境只能运行与其自身版本相同或者更低版本编译的类文件。
下面来验证下,把有问题的jar解压一下:
jar -xvf org.eclipse.core.runtime-3.31.100.jar
把有报错这个类反编译一下:
javap -verbose org/eclipse/core/runtime/Plugin.class
可以看到这个类确实是由Java 17(版本61.0)编译生成的,反编译后的字节码指令中,major version的值是61:
Last modified 2024-5-24; size 9363 bytes
MD5 checksum b41961b4155bfdabeeb67952fdec406f
Compiled from "Plugin.java"
public abstract class org.eclipse.core.runtime.Plugin implements org.osgi.framework.BundleActivator
minor version: 0
major version: 61
flags: ACC_PUBLIC, ACC_SUPER, ACC_ABSTRACT
Constant pool:
#1 = Class #2 // org/eclipse/core/runtime/Plugin
#2 = Utf8 org/eclipse/core/runtime/Plugin
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Class #6 // org/osgi/framework/BundleActivator
#6 = Utf8 org/osgi/framework/BundleActivator
#7 = Utf8 PLUGIN_PREFERENCE_SCOPE
省略……
记录一下每个版本的 Java 对应的类文件格式版本号major version(截止2024-07-18):
Java SE 1.1 = 45
Java SE 1.2 = 46
Java SE 1.3 = 47
Java SE 1.4 = 48
Java SE 5.0 = 49
Java SE 6.0 = 50
Java SE 7.0 = 51
Java SE 8.0 = 52
Java SE 9.0 = 53
Java SE 10 = 54
Java SE 11 = 55
Java SE 12 = 56
Java SE 13 = 57
Java SE 14 = 58
Java SE 15 = 59
Java SE 16 = 60
Java SE 17 = 61
Java SE 18 = 62
Java SE 19 = 63
Java SE 20 = 64
三、解决
那这个问题怎么解决呢?
1 . 升级当前环境的jdk版本,操作简单,但一般不太现实
2 . 降低对应依赖的版本
比如在我这个项目中,有问题(编译时Java版本太高)的包是org.eclipse.core.runtime,版本是3.31.100,那么就需要降低这个包的版本。大概有以下几种做法:
(1)如果项目中直接引用了这个包(比如在pom文件中定义了),那直接修改版本号就行(试着一点一点 降版本 -> 编译试试 -> 不行再降降版本 -> 再编译试试……)
(2)如果项目中没有直接引用这个包,那可以通过maven依赖树看下是哪个包引用的它,还是以我这个项目为例:
mvn dependency:tree -Dverbose
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< org.jacoco:org.jacoco.core >---------------------
[INFO] Building JaCoCo :: Core 0.8.4
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- dependency:2.2:tree (default-cli) @ org.jacoco.core ---
[INFO] org.jacoco:org.jacoco.core:jar:0.8.4
[INFO] +- org.ow2.asm:asm:jar:7.1:compile
[INFO] +- org.ow2.asm:asm-commons:jar:7.1:compile
[INFO] | +- (org.ow2.asm:asm:jar:7.1:compile - omitted for duplicate)
[INFO] | +- (org.ow2.asm:asm-tree:jar:7.1:compile - omitted for duplicate)
[INFO] | \- org.ow2.asm:asm-analysis:jar:7.1:compile
[INFO] | \- (org.ow2.asm:asm-tree:jar:7.1:compile - omitted for duplicate)
[INFO] +- org.ow2.asm:asm-tree:jar:7.1:compile
[INFO] | \- (org.ow2.asm:asm:jar:7.1:compile - omitted for duplicate)
[INFO] +- org.eclipse.jdt:org.eclipse.jdt.core:jar:3.19.0:compile
[INFO] | +- org.eclipse.platform:org.eclipse.core.resources:jar:3.20.200:compile
[INFO] | | +- org.eclipse.platform:org.eclipse.core.expressions:jar:3.9.400:compile
[INFO] | | | \- (org.eclipse.platform:org.eclipse.core.runtime:jar:3.31.100:compile - omitted for duplicate)
[INFO] | | +- (org.eclipse.platform:org.eclipse.core.filesystem:jar:1.10.400:compile - omitted for duplicate)
[INFO] | | +- (org.eclipse.platform:org.eclipse.core.runtime:jar:3.31.100:compile - omitted for duplicate)
[INFO] | | \- org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile
[INFO] | +- org.eclipse.platform:org.eclipse.core.runtime:jar:3.31.100:compile
[INFO] | | +- (org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile - omitted for duplicate)
[INFO] | | +- org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile
[INFO] | | | \- (org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile - omitted for duplicate)
[INFO] | | +- org.eclipse.platform:org.eclipse.core.jobs:jar:3.15.300:compile
[INFO] | | | +- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | | | \- (org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile - omitted for duplicate)
[INFO] | | +- org.eclipse.platform:org.eclipse.equinox.registry:jar:3.12.100:compile
[INFO] | | | \- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | | +- org.eclipse.platform:org.eclipse.equinox.preferences:jar:3.11.100:compile
[INFO] | | | +- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | | | +- org.osgi:org.osgi.service.prefs:jar:1.1.2:compile
[INFO] | | | | \- org.osgi:osgi.annotation:jar:8.0.1:compile
[INFO] | | | \- (org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile - omitted for duplicate)
[INFO] | | +- org.eclipse.platform:org.eclipse.core.contenttype:jar:3.9.400:compile
[INFO] | | | +- (org.eclipse.platform:org.eclipse.equinox.preferences:jar:3.11.100:compile - omitted for duplicate)
[INFO] | | | +- (org.eclipse.platform:org.eclipse.equinox.registry:jar:3.12.100:compile - omitted for duplicate)
[INFO] | | | +- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | | | \- (org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile - omitted for duplicate)
[INFO] | | \- org.eclipse.platform:org.eclipse.equinox.app:jar:1.7.100:compile
[INFO] | | +- (org.eclipse.platform:org.eclipse.equinox.registry:jar:3.12.100:compile - omitted for duplicate)
[INFO] | | \- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | +- org.eclipse.platform:org.eclipse.core.filesystem:jar:1.10.400:compile
[INFO] | | +- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | | +- (org.eclipse.platform:org.eclipse.equinox.registry:jar:3.12.100:compile - omitted for duplicate)
[INFO] | | +- (org.eclipse.platform:org.eclipse.osgi:jar:3.20.0:compile - omitted for duplicate)
[INFO] | | \- (org.eclipse.platform:org.eclipse.core.runtime:jar:3.31.100:compile - omitted for duplicate)
[INFO] | \- org.eclipse.platform:org.eclipse.text:jar:3.14.100:compile
[INFO] | +- org.eclipse.platform:org.eclipse.core.commands:jar:3.12.100:compile
[INFO] | | \- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | +- (org.eclipse.platform:org.eclipse.equinox.common:jar:3.19.100:compile - omitted for duplicate)
[INFO] | +- (org.eclipse.platform:org.eclipse.equinox.preferences:jar:3.11.100:compile - omitted for duplicate)
[INFO] | \- (org.eclipse.platform:org.eclipse.core.runtime:jar:3.31.100:compile - omitted for duplicate)
[INFO] \- org.eclipse.jgit:org.eclipse.jgit:jar:5.5.0.201909110433-r:compile
[INFO] +- com.jcraft:jsch:jar:0.1.55:compile
[INFO] +- com.jcraft:jzlib:jar:1.1.1:compile
[INFO] +- com.googlecode.javaewah:JavaEWAH:jar:1.1.6:compile
[INFO] +- org.slf4j:slf4j-api:jar:1.7.2:compile
[INFO] +- org.bouncycastle:bcpg-jdk15on:jar:1.61:compile
[INFO] | \- (org.bouncycastle:bcprov-jdk15on:jar:1.61:compile - omitted for duplicate)
[INFO] +- org.bouncycastle:bcprov-jdk15on:jar:1.61:compile
[INFO] \- org.bouncycastle:bcpkix-jdk15on:jar:1.61:compile
[INFO] \- (org.bouncycastle:bcprov-jdk15on:jar:1.61:compile - omitted for duplicate)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.700 s
[INFO] Finished at: 2024-07-18T22:08:14+08:00
[INFO] ------------------------------------------------------------------------
通过依赖树可以发现,在项目(pom文件)中是org.eclipse.jdt.core引用了它,并且org.eclipse.jdt.core的版本是3.19.0,那可以试着降低org.eclipse.jdt.core的版本号,比如3.18.0、3.17.0……
但是,也有可能org.eclipse.jdt.core很多个版本依赖的都是同一个有问题的版本,比如3.19.0和3.18.0这两个版本的org.eclipse.jdt.core 依赖的org.eclipse.core.runtime的版本是号都是3.31.100的,这时也可以直接用依赖管理dependencyManagement和依赖排除来强制指定org.eclipse.core.runtime的版本,比如在pom文件中强制指定org.eclipse.core.runtime的版本(我在https://mvnrepository.com/中把org.eclipse.core.runtime所有的版本号都试了一下,最终找到3.22.0版本是Java 8编译的):
直接用依赖管理强制指定版本:
<dependencies>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.19.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.core.runtime</artifactId>
<version>3.22.0</version>
</dependency>
</dependencies>
</dependencyManagement>
或者先排除,再引入:
<dependencies>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.19.0</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.core.runtime</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.core.runtime</artifactId>
<version>3.22.0</version>
</dependency>
</dependencies>
四、总结
上面的包名长得都很像,写的我都晕了,画个图总结下。假如用B来表示一个maven依赖,编译时,如果报错信息提示编译B的java版本太高(假如B就是文章开头图中提示报错的包org.eclipse.core.runtime)
(1)如果项目中直接引用了B,可以直接降低B的版本
(2)如果项目中是有一个依赖A引用了B
可以试着一点一点降低A的依赖:
也可以直接用依赖管理dependency management和依赖排除来强制指定B的版本:
转载请注明出处《错误的类文件: *** 类文件具有错误的版本 61.0, 应为 52.0 请删除该文件或确保该文件位于正确的类路径子目录中 》 https://blog.csdn.net/huyuyang6688/article/details/140532981