Can you compile a class using Java 8 and then use it in Java 7?
I'd like to write a utility JAR with a simple interface (Java 7 compatible) but using lambdas all over the place inside. Then I'd like to use the utility in some code that has to be compiled with JDK 7..
is it possible?
As you can see, there are some contradictory answers.. so, what's the truth? ;-)
Backward CompatibilityJava versions are expected to be binary backwards-compatible. For example, JDK 8 can run code compiled by JDK 7 or JDK 6. It is common to see applications leverage this backwards compatibility by using components built by different Java version.
Yes, you can set the version of compiler at compile time. And compile your java code into old versions of java. Here we use javac to compile code that will run on a 1.4 VM. You might also need following parameter to set denote the version of your code.
As answered already you are mostly safe and most products and 3rd party libraries will simply work. However there do exist very rare cases where binary incompatibilities (ones where the class file compiled using older JDK will fail to run in the newer JVM) were introduced between JDK versions.
You can use -source 1.7 -target 1.7
when compiling with java 8 javac to make .classes that work on java 7. However, you don't get java 8 features such as lambdas then, as you have to use 1.7 as source value as well.
That's not the end of story though. In this answer it was explained that there aren't actually new JVM instructions, so this should be possible. In this answer the tool retrolambda was introduced which can be used to run java 8 code on older JVMs. Author claims that compilation step is not required, just a java agent transforming the classes. His solution deals with lambdas only, not any other features. Of course, that won't bring you the new APIs coming with java 8, or other improvements, but at least it would make what you ask possible. Some of the new apis have also been unofficially backported, namely java.util.stream and java.time.
If we were in pre-java8 era, even though -source 1.8 -target 1.7
is not supported by javac you could still use Compiler API to do the same. Also Eclipse compiler has been able to do this, as well as ant and maven tasks that use either of the two mentioned options (compiler-plugin uses javac by default). This doesn't seem to no longer be so straight forward, as using other compilers you'd need the implementations of features like lambdas as well, and Compiler API will throw the same "javac: source release 1.8 requires target release 1.8" as others.
For the interested, here's what happens going that way using Eclipse compiler & Maven and Calculator example code:
pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>fi.eis.applications.java8</groupId>
<artifactId>calculator</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.7</target>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
Execution on Windows:
>mvn clean compile
[..snip..]
[INFO] BUILD SUCCESS
>cd target\classes
>"%JAVA_HOME%\bin\java.exe" Calculator
Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/invoke/LambdaMetafactory
at Calculator.main(Calculator.java:16)
Caused by: java.lang.ClassNotFoundException: java.lang.invoke.LambdaMetafactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
So one would need to implement those classes in pure java as a third party library to get that to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With