2

I have a maven project. It's written in Java 16. I have the Java 16 JDK installed.

When I build it with dockerfile, everything works, but when I run docker and I go on my project url I got an "unsupported class file major version 60".

Is that possible to run java 16 project on tomcat or on something else ?

There is my some of my files:

DockerFile:

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"]

And my 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 log:

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$0(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.

Log from api container after a docker exec:

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)
  • 2
    Can you provide the **fully stacktrace**? – Joachim Sauer Jul 31 '21 at 15:20
  • 2
    *but when I run docker and I go on my project url I got an "unsupported class file major version 60".* It will be running with a lower version than 1.16. Check what `java -version` gives you and then change your PATH so that >= 1.16 is in it – g00se Jul 31 '21 at 15:48
  • Full stacktrace is provide @JoachimSauer. And I add the log when I run the `java -version` in docker container @g00se :) – Vincent Moittie Aug 01 '21 at 07:53
  • @VincentMoittie: which version of Jersey are you using? – Piotr P. Karwasz Aug 01 '21 at 08:19
  • 3
    The issue seems to be The Jersey library (or specifically: the ASM version that it includes): Both Maven and Tomcat are fine with Java 16, but that library doesn't support Java 16. Normally Java libraries tend to be upwards compatible (i.e. don't need extra support), but since ASM tries to read and interpret class files directly it needs to be fully updated to be able to work with classes compiled on later JDKs.. Try the latest release of your Jersey major version first and if that doesn't work you might need to file a bug and/or build it yourself with a newer ASM version. – Joachim Sauer Aug 01 '21 at 09:30
  • 2
    [This PR](https://github.com/eclipse-ee4j/jersey/pull/4754) should fix the issue, but I don't know if it's been released and if so in which versions. – Joachim Sauer Aug 01 '21 at 09:32
  • 1
    @JoachimSauer: version 2.33 already supports Java 16 (cf. [source code](https://github.com/eclipse-ee4j/jersey/blob/c34ed1d947875dea0eb4f532181c53800bea3569/core-server/src/main/java/jersey/repackaged/org/objectweb/asm/ClassReader.java#L187)). – Piotr P. Karwasz Aug 01 '21 at 09:39

1 Answers1

10

As already remarked in the comments by Joachim, your problem is due to the ASM version packaged by Jersey. It is similar to this question regarding Spring.

The easiest way to find the highest version of Java supported by ASM is to look at the source code:

  • Jersey 2.35 supports up to Java 18,
  • Jersey 2.34 supports up to Java 17 (cf. source code),
  • Jersey 2.33 supports up to Java 16,
  • Jersey 2.30 supports up to Java 15 (with a warning for Java 15),
  • Jersey 2.29 supports up to Java 14 (with a warning for Java 14),
  • Jersey 2.28 (first EE4j version) supports up to Java 12.

As for the 3.x branch, all versions support Java 16, while the latest (3.0.2) supports also the upcoming Java 17.

Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43