如何在 tomcat9 中修复“不支持的 class 文件主要版本 60”?

How to fix “unsupported class file major version 60” in tomcat9?

我有一个maven项目。它写在 Java 16 中。我安装了 Java 16 JDK。

当我使用 docker 文件构建它时,一切正常,但是当我 运行 docker 继续我的项目 url 时,我得到了一个“不受支持的 class 文件主要版本 60".

是否有可能 运行 java 16 项目 tomcat 或其他项目?

这是我的一些文件:

Docker文件:

FROM maven:3.8.1-openjdk-17 as builder
RUN mkdir -p /root/.m2 && mkdir /root/.m2/repository
COPY . /app/
RUN cd /app && mvn clean package -Dmaven.test.skip=true

FROM tomcat:9.0-jdk16-openjdk
COPY --from=builder /app/target/demo.war /usr/local/tomcat/webapps
ENV CATALINA_OPTS=""
EXPOSE 8080
CMD ["catalina.sh", "run"]

还有我的pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.demo</groupId>
    <artifactId>demo</artifactId>
    <packaging>war</packaging>
    <version>0.0.1</version>
    <name>demo</name>
    <url>http://maven.apache.org</url>

    <properties>
        <!-- Dependencies properties -->
            <!-- ... -->
        <!-- Project build properties -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>16</maven.compiler.source>
        <maven.compiler.target>16</maven.compiler.target>
        <maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
        <maven.resources.plugin>3.0.1</maven.resources.plugin>
        <maven-war-plugin.version>3.2.2</maven-war-plugin.version>
        <java.version>16</java.version>
    </properties>

    <dependencies>
        <!-- ... -->
    </dependencies>
    <build>
        <finalName>demo</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>${java.version}</release>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M5</version>
            </plugin>
            <!-- ... -->
        </plugins>
    </build>
</project>

Tomcat日志:

Type Rapport d'exception

message Servlet.init() for servlet [demo-serlvet] threw exception

description Le serveur a rencontré une erreur interne qui l'a empêché de satisfaire la requête.

exception

javax.servlet.ServletException: Servlet.init() for servlet [demo-serlvet] threw exception
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:831)
cause mère

java.lang.IllegalArgumentException: Unsupported class file major version 60
    jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:201)
    jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:179)
    jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:165)
    jersey.repackaged.org.objectweb.asm.ClassReader.<init>(ClassReader.java:289)
    org.glassfish.jersey.server.internal.scanning.AnnotationAcceptingListener.process(AnnotationAcceptingListener.java:148)
    org.glassfish.jersey.server.ResourceConfig.scanClasses(ResourceConfig.java:888)
    org.glassfish.jersey.server.ResourceConfig._getClasses(ResourceConfig.java:842)
    org.glassfish.jersey.server.ResourceConfig.getClasses(ResourceConfig.java:751)
    org.glassfish.jersey.server.ResourceConfig$RuntimeConfig.<init>(ResourceConfig.java:1178)
    org.glassfish.jersey.server.ResourceConfig$RuntimeConfig.<init>(ResourceConfig.java:1151)
    org.glassfish.jersey.server.ResourceConfig.createRuntimeConfig(ResourceConfig.java:1147)
    org.glassfish.jersey.server.ApplicationHandler$RuntimeConfigConfigurator.init(ApplicationHandler.java:182)
    org.glassfish.jersey.server.ApplicationHandler.lambda$initialize[=13=](ApplicationHandler.java:290)
    java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4203)
    org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:290)
    org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:259)
    org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
    org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
    org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:346)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:831)
note La trace complète de la cause mère de cette erreur est disponible dans les fichiers journaux de ce serveur.

在 docker 执行后从 api 容器登录:

root@df012b95a989:/usr/local/tomcat# java -version
openjdk version "16.0.2" 2021-07-20
OpenJDK Runtime Environment (build 16.0.2+7-67)
OpenJDK 64-Bit Server VM (build 16.0.2+7-67, mixed mode, sharing)

正如 , your problem is due to the ASM version packaged by Jersey. It is similar to this question 在关于 Spring 的评论中所说的那样。

查找ASM支持的Java最高版本的最简单方法是查看源代码:

  • Jersey 2.35 最多支持 Java 18,
  • Jersey 2.34 最多支持 Java 17(参见 source code),
  • Jersey 2.33 最多支持 Java 16,
  • Jersey 2.30 最多支持 Java 15(带有 Java 15 的警告),
  • Jersey 2.29 最多支持 Java 14(带有 Java 14 的警告),
  • Jersey 2.28(第一个 EE4j 版本)最多支持 Java 12.

至于3.x分支,所有版本都支持Java16,而最新的(3.0.2)也支持即将到来的Java17.