I have my code written in Java 17. I was wondering if there is a way to compile to older Java versions (8 and onwards).
Many folks online suggest that I should use something like this:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
However, when I do that, I get the following issue:
Caused by: java.lang.IllegalStateException: warning: source release 17 requires target release 17
Using release
with maven-compiler-plugin instead did not help either.
What I don't understand is that if the target and source need to be exactly the same, then why do we event need both?
I am using Maven 3.8.3, by the way.
CodePudding user response:
Your expectations of the JDK are wrong with regards to compiler compatibility. The compiler is not forward compatible, it is backwards compatible. Therefore, in your case, setting the compiler target
to Java 1.8 with source
at Java 17 will not work.
There are new features in Java 17 which are not compatible with Java 1.8 and therefore Java JDK 1.8 will not understand what they are and will definitely throw Syntax Errors. That explains the warning you are getting from the Maven Compiler plugin.
At the same time, Java 17 is too far ahead. While it will understand all the syntax present in previous versions of Java, you will encounter compile time errors due to missing classes. An example of such an error is java.lang.NoClassDefFoundError
or java.lang.ClassNotFoundException
as some classes have been deprecated and removed.
Starting with Java 9, Java decided to only support a maximum of three versions back. Therefore if your are working with Java 17 the last support would be Java 14. In this case, if you write all code compatible with JDK 14 and compile with JDK 17, it would continue to work for all versions in between.
This is similar to how it has always been with Java 1.8 and below. The code has to be compatible with your target environment. So, if your targetCompatibility
is Java 1.8, then your sourceCompatibility
should also be Java 1.8 and below.
An example:
<!-- Correct -->
<properties>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- Wrong -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
CodePudding user response:
It's not always the case that you can't compile with downwards compatibility. However, just as 1.8 introduced lambdas, which couldn't be made compatible with pre-1.8 runtimes, 17 includes new features (particularly sealed classes) that older runtimes can't understand. If you want to tell the compiler "I won't use those features, so you can be compatible", you set your compiler release to an older version.