Home > Blockchain >  Dockerize my gradle java project but encounter jdk version mismatch between compile time and runtime
Dockerize my gradle java project but encounter jdk version mismatch between compile time and runtime

Time:07-02

I am developing a gradle java project (it is pure java not spring-boot).

I dockerize the project with multi-stage Dockerfile in order to slim the final image size:

FROM gradle:7.4.2-alpine as builder
WORKDIR /home/app
COPY . .
RUN gradle :myapp:build

FROM openjdk:8-jre-alpine as my-app
WORKDIR /app
COPY --from=builder /home/app/MyApp/build/libs/MyApp-1.0-SNAPSHOT.jar /app/
ENTRYPOINT ["java", "-jar", "/app/MyApp-1.0-SNAPSHOT.jar"]

As you see above, I am using base image openjdk:8-jre-alpine for running the application jar. I choose it as base image because it is very slim.

I build the project by docker build -t myapp . & it is successful.

I run it by docker run myapp, however I get error:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/MyApp 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 52.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)

My interpretation of the error is my Java class is built with a higher JDK version while at runtime the the base image I choose openjdk:8-jre-alpine is using an older version JRE to run. (Please correct me if I am wrong here.)

I would like to keep using that base image because it is small in size. So I decided to compile my code using java 11 jdk.

I tried specifying the older java version for building project by adding the following in my build.gradle :

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

and then, build the image again docker build -t myapp ., but now I get building error:

#12 45.30 Could not determine the dependencies of task ':myapp:compileJava'.
#12 45.30 > Could not resolve all dependencies for configuration ':common:compileClasspath'.
#12 45.30    > Failed to calculate the value of task ':myapp:compileJava' property 'javaCompiler'.
#12 45.31       > Provisioned toolchain '/home/gradle/.gradle/jdks/adoptium-11-x64-hotspot-linux' could not be probed.

I guess that is because the base image I use doesn't have that jdk?? (Please correct me if I understood wrongly here)

So, I wonder what is the proper way to have my project being built by java 11 jdk & I could still use that base image?

===== More try I did =====

I forgot to mention that I also guessed the image openjdk:8-jre-alpine might hint it only support java-8, so I renamed it to openjdk:11-jre-alpine for java-11, when build the image I encounter the following error, I guess it means the image doesn't exist?

[ ] Building 1.5s (6/6) FINISHED                                                                                                                                                                                        
 => [internal] load build definition from Dockerfile                                                                                                                                                               0.0s
 => => transferring dockerfile: 386B                                                                                                                                                                               0.0s
 => [internal] load .dockerignore                                                                                                                                                                                  0.0s
 => => transferring context: 34B                                                                                                                                                                                   0.0s
 => ERROR [internal] load metadata for docker.io/library/openjdk:11-jre-alpine                                                                                                                                     1.4s
 => CANCELED [internal] load metadata for docker.io/library/gradle:7.4.2-alpine                                                                                                                                    1.4s
 => [auth] library/gradle:pull token for registry-1.docker.io                                                                                                                                                      0.0s
 => [auth] library/openjdk:pull token for registry-1.docker.io                                                                                                                                                     0.0s
------
 > [internal] load metadata for docker.io/library/openjdk:11-jre-alpine:
------
failed to solve with frontend dockerfile.v0: failed to create LLB definition: docker.io/library/openjdk:11-jre-alpine: not found

CodePudding user response:

From oracle documentation

Java SE | Released | Major | Supported majors

1.0.2 | May 1996 | 45 | 45

1.1 | February 1997 | 45 | 45

1.2 | December 1998 | 46 | 45 .. 46

1.3 | May 2000 | 47 | 45 .. 47

1.4 | February 2002 | 48 | 45 .. 48

5.0 | September 2004 | 49 | 45 .. 49

6 | December 2006 | 50 | 45 .. 50

7 | July 2011 | 51 | 45 .. 51

8 | March 2014 | 52 | 45 .. 52

9 | September 2017 | 53 | 45 .. 53

10 | March 2018 | 54 | 45 .. 54

11 | September 2018 | 55 | 45 .. 55

12 | March 2019 | 56 | 45 .. 56

13 | September 2019 | 57 | 45 .. 57

14 | March 2020 | 58 | 45 .. 58

15 | September 2020 | 59 | 45 .. 59

16 | March 2021 | 60 | 45 .. 60

17 | September 2021 | 61 | 45 .. 61

18 | March 2022 | 62 | 45 .. 62

Your error says

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 52.0

You have compiled with JAVA 17 and try to run it with JAVA 8. Switch either the compilation or the environment that runs the compiled application according to the above table.

Your JRE 8 that exists in docker supports any code that is compiled with JDK 8 or earlier versions (1 .. 5, 6, 7) .

If you wish to compile the project with JDK 17 you need to provide a running environment in docker >= JDK 17.

Edit:

Answering the comment

I also wonder what is the image I should use to run the code that is compiled by JDK 17

try with

FROM openjdk:17-alpine as my-app ...
  • Related