4

I have a Java 10+ based source code which I want to compile for a lower version of Java (e.g. Java 8) without modifications of the source itself. I want users with Java 8 installed to be able to run the executable JAR file.

Is this possible and if yes, how can this be done using maven? I didn't find any reasonable guides on this. Lowering the source and target compiler options does not work: I still get the version mismatch error.

LauncherClient.java:

import lombok.Getter;
import lombok.val;

public class LauncherClient
{
    @Getter
    private String lombok = "Lombok";

    public static void main(String[] arguments)
    {
        val launcherClient = new LauncherClient();
        var message = "Hello world, ";
        System.out.println(message + launcherClient.getLombok());
    }
}

pom.xml:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>Java11Test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>LATEST</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>11</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <!-- Build an executable JAR -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>LauncherClient</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

When running the executable JAR via the command line using Java 8:

java -jar Java11Test-1.0-SNAPSHOT.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: LauncherClient 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(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$100(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

Running it using Java 11 works fine:

"C:\Program Files\Java\jdk-11.0.1\bin\java.exe" -jar Java11Test-1.0-SNAPSHOT.jar
Hello world, Lombok
7
  • Did you check stackoverflow.com/questions/19654557/…
    – Ori Marko
    Commented Nov 15, 2018 at 13:04
  • can't see jdk version dependency in your pom.xml file?To solve this I suggest to go into your pom file and check the <jdk.version>1.7</jdk.version>. Commented Nov 15, 2018 at 13:06
  • It's not just the bytecode version, it's also that you cannot use any API introduced after JDK8 (and the compiler target settings won't check for that). I'd install a full JDK 8 as well and use that to compile to make sure I did not miss anything.
    – Thilo
    Commented Nov 15, 2018 at 13:31
  • 1
    @Thilo: I have a full JDK 8 installed but it can't compile the code since it uses Java 10 features (e.g. the var keyword). So essentially you can't compile in "compatibility mode" as desired how it seems. Commented Nov 15, 2018 at 13:51
  • Interesting problem. For things like the var keyword it should still be able to cross-compile down to 8. I wonder if Lombok also plays a role here (since it does annotation processing on the bytecode). Does it work for your sample class if you remove Lombok and/or remove the var ? (Just trying to figure out where it fails exactly)
    – Thilo
    Commented Nov 15, 2018 at 14:23

0