Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to compile Java11 code to Java8 bytecode and run on 8?

Tags:

java

maven

I'm playing with some dependencies and compilation to older releases using java 11. I migrated one dependency to Java 11 and works fine, but we still have to run it Tomcat 7 or 8 on Java8. Is it possible to use the --release flag to compile code which uses var, stream().dropwhile(...) or Map.of(...) and run on 8?

Release flag suggest that it should be possible:

--release release Compiles against the public, supported and documented API for a specific VM version. Supported release targets are 6, 7, 8, and 9.

This project is a dependency, stand-alone works fine with SprinBoot2.1 and Java11, but needs to be run in Java8.

My maven plugin compiler settings:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <release>8</release>
    </configuration>
</plugin>

but this forbids compiling >jdk8 specific code. I'm using latest maven 3.6.0 and mvn compiler as above.

Attempt to compile:

return List.of("dsadas", "dasdadddds", "£dsada", "dasdas")
        .stream()
        .dropWhile(s -> s.contains("das"))
        .collect(Collectors.toList());

throws error:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project api: Compilation failure: Compilation failure: 
[ERROR] /home/agilob/Projects/.....java:[58,13] cannot find symbol
[ERROR]   symbol:   class var
[ERROR]   location: 
[ERROR] /home/agilob/Projects/....java:[43,20] cannot find symbol
[ERROR]   symbol:   method of(java.lang.String,java.lang.String,java.lang.String,java.lang.String)
[ERROR]   location: interface java.util.List
[ERROR] -> [Help 1]
like image 756
agilob Avatar asked Nov 15 '18 17:11

agilob


People also ask

Can Java 11 compiled code run on Java 8 JVM?

The class files created by Java 8 are still executable in Java 11; however, there have been other changes in the Java runtime (library changes, etc.) that might require modification of the code. These modifications may be made in Java 8 and compiled with Java 8 making it compatible with the Java 11 runtime.

Is Java 17 backwards compatible?

In general Java is extremely backward compatible. There have been a few minor breaking changes from JDK 8 to JDK 17, but the worst ones have had command-line options to disable them.


Video Answer


2 Answers

It is not possible. Only the API methods and classes of the targeted Java platform are allowed.

That is defined in JEP 247: Compile for Older Platform Versions

A new command-line option, --release, is defined, which automatically configures the compiler to produce class files that will link against an implementation of the given platform version.

The relevant part that says what can be used is:

For N < 9, the documented APIs consist of the public APIs that were on javac's default bootclasspath for JDK N.

For N >= 9, the documented APIs consist of (i) the APIs exported from those modules in the JDK image which are part of the documentation of JDK N; and (ii) the API exported from the jdk.unsupported module (documented in JEP 260).

like image 114
lalo Avatar answered Oct 18 '22 11:10

lalo


It is possible now with https://github.com/bsideup/jabel

Jabel - javac 12 plugin that makes it emit Java 8 bytecode

like image 20
agilob Avatar answered Oct 18 '22 10:10

agilob