3

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
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • Did you check https://stackoverflow.com/questions/19654557/how-to-set-specific-java-version-to-maven – Ori Marko Nov 15 '18 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 1.7. – GauravRai1512 Nov 15 '18 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 Nov 15 '18 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. – BullyWiiPlaza Nov 15 '18 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 Nov 15 '18 at 14:23
  • bad news: The source version cannot be greater than the target version (https://stackoverflow.com/a/49387212/14955). So I guess you cannot use new language features and compile down to 8. I wonder why Maven does not raise an error about this. Maybe you can settle with Java 8 + Lombok (or give up on Java 8 compat) – Thilo Nov 15 '18 at 14:28
  • It will never work if you compile with 10 and run on 8 only if you use things like `8` on JDK9+ ...cause you need to make sure your code does not use language things from higher versions... – khmarbaise Nov 15 '18 at 16:28

0 Answers0