Search code examples
javaspringspring-bootjava-11java-17

How to solve java.lang.UnsupportedClassVersionError error? Where can I found the right JRE version?


I am working on a Java application (a Spring Boot application). On my Ubuntu development machine I have used this JDK version:

andrea@ubuntu:~$ java --version
java 17 2021-09-14 LTS
Java(TM) SE Runtime Environment (build 17+35-LTS-2724)
Java HotSpot(TM) 64-Bit Server VM (build 17+35-LTS-2724, mixed mode, sharing)

This is the pom.xml file of my Spring Boot application:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.notariato</groupId>
    <artifactId>UpdateInfoBatch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>UpdateInfoBatch</name>
    <description>Recupera ed aggiorna le informazioni relative alla lista dei notai ed ai distretti notarili</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.batch</groupId>
            <artifactId>spring-batch-test</artifactId>
            <scope>test</scope>
        </dependency>
        
        
        <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
    

    
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>
        
        
        
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>2.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-client</artifactId>
            <version>2.4.3</version>
        </dependency>
        
    
    
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

I obtained the .jar application and I have no problem running it on my development machine.

The problem happened when I tried to move this .jar file on the production machine.

Here the Java version is the following one:

[email protected] [~/java/jre1.8.0_311/bin]# ./java -version
java version "1.8.0_311"
Java(TM) SE Runtime Environment (build 1.8.0_311-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.311-b11, mixed mode)
[email protected] [~/java/jre1.8.0_311/bin]#

So, as you can see, here the JAVA version seems to be the 1.8.0_311

Running my application I obtained this error message:

[email protected] [~/java/jre1.8.0_311/bin]# ./java -jar /home/webadmin/notartel-import-data-batch/UpdateInfoBatch-0.0.1-SNAPSHOT.jar
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/notariato/updateInfo/UpdateInfoBatchApplication has been compiled by a more recent version of the Java Runtime (class file version 55.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:756)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:46)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)

It seems that the installed JRE is too old. I was trying to manually download the JRE package for JAVA 17 but I cannot find it.

What version of the JRE have I to use? Where can I download this JRE package version? (not with the yum package manager, I need to download the tar file containing the JRE and then extract it on my system).

Thank you


Solution

  • Traditional JREs no longer exist since Java 9 (although some vendors offer JRE-like packages). In order to get a Java runtime to run your application you can use the jlink tool, which also comes with JDK 17, like this for a modular application:

    jlink -p <directory app jar> --add-modules <name of your module> --output custom_runtime
    

    If your application is non-modular, you will have to find out which modules you need, for instance using jdeps (also a tool that comes with JDK 17):

    $ mvn dependency:build-classpath -DincludeScope=runtime -Dmdep.outputFile=cp.txt
    $ jdeps -classpath "<contents of cp.txt>" --multi-release 17 --print-module-deps --ignore-missing-deps <app jar>
    

    Which prints something like mod1,mod2,mod3. Pass them to the --add-modules flag instead:

    jlink --add-modules mod1,mod2,mod3 --output custom_runtime
    

    This will generate a custom_runtime folder with a Java runtime you can use to run your app, which can then be deployed on the target machine.

    If your app is non-modular you will also have to deploy the app .jar file, and all of it's dependencies (there should be no external runtime dependencies for a Spring Boot project, since it bundles all dependencies in the app jar). Then, use the java executable in the custom runtime to run the app:

    /path/to/custom/runtime/java -jar <app jar>