13

In order to reduce the clutter caused by numerous instantiations of anonymous types, I'm exploring the possibility of leveraging Java 8 lambdas.

One important consideration before using Java 8 and lambdas in a production environment is whether JDK8-compiled code that uses lambda expressions can be executed on an earlier version of the Java runtime. I'm specifically interested in JRE6 and JRE7 as target platforms.

One one hand, I understand that lambdas are simply syntactic sugar around an instantiation of an anonymous class containing one method. On the other hand, I'm not certain that this equivalence implies that the bytecode generated for each is identical and/or compatible across JVM versions other than JRE8.

For example, given the single-method interface:

public interface Action<T> {
    public void perform(T argument);
}

The following two snippets are "functionally" equivalent:

With lambda:

final Action<String> y = i -> System.out.println(i);

With anonymous class instance:

final Action<String> y = new Action<String>() {
    @Override
    public void perform(final String i) {
        System.out.println(i);
    }
};

My specific question is whether the semantic equivalence of both constructs extends to equivalence of their compiled representations. Furthermore, if they indeed compile equivalently, does this equivalence indicate that the compiled form of a lambda expression can be hosted on earlier versions of the Java runtime without modification?

bnu
  • 133
  • 4
  • It would be possible to make lambdas work on Java 7 VMs, but the official compiler does not do that. – user253751 Mar 22 '14 at 02:25
  • 2
    IMO it would be better to upgrade your JRE to Java 8 instead of trying to use tricks or hacks to make lambdas work on JRE6/7; not only because you then get Java 8 features, but also because JRE 6 and 7 are end-of-life and won't get any free (security) updates anymore from Oracle. – Jesper Jun 20 '16 at 10:17
  • 3
    Also, lambdas are not converted and compiled into anonymous classes by the JDK 8 compiler; it uses a more efficient representation so that no anonymous class is necessary. – Jesper Jun 20 '16 at 10:18

4 Answers4

9

In general it is not possible to have Javac compiler use a source level that is higher than the target JVM level. Thus the answer is NO.

anttix
  • 7,709
  • 1
  • 24
  • 25
  • 2
    Javac does not support compiling newer language features for older JVMs. It has been the case for all previous versions and AFAIK is the case for Java 8 as well. See: http://stackoverflow.com/questions/18320587/javac-cross-compilation-with-1-7 . In-general is there because Javac is not the only compiler out there so someone might build a compiler that does support it. – anttix Mar 22 '14 at 01:54
  • 1
    @user2864740 the post you are referring to discusses a completely different issue: It claims that there are inconsistencies in how different versions of the javac compiler handle code despite being set to the same source level. – anttix Mar 22 '14 at 02:02
  • Thanks for backing up your answer. – user2864740 Mar 22 '14 at 02:13
  • 5
    In addition to the target JVM level (really, classfile version), lambdas also require runtime support that was added in Java 8 that is not present in Java 7. – Stuart Marks Mar 22 '14 at 06:08
7

Officially no, but for an unofficial solution you should look at the Retrolambda project. It doesn't backport the Collection API changes, but it can handle lambda expressions (and method references) for you.

seanf
  • 6,504
  • 3
  • 42
  • 52
  • 2
    Have good unit tests and run them on the processed classes. If there is a bug in retrolambda, you want to know it up front. – Thorbjørn Ravn Andersen Apr 24 '16 at 16:57
  • Excellent !. Just what I was looking for. I can enjoy Java 8 features for personal libs, Knowing that if needed Retrolamba can help to prepare it for older versions :) – Davor Hrg May 28 '17 at 14:03
3

I dont believe so - the bytecode version is different (52 i think) and lambda uses invokedynamic and not get translated into anonymous classes..

bennyl
  • 2,886
  • 2
  • 29
  • 43
  • 3
    Invokedynamic is also available in 1.7. Lambdas are implemented using method references which is a new feature. – anttix Mar 22 '14 at 02:00
0

Java 8 introduces a new concept of default method implementation in interfaces. This capability is added for backward compatibility so that old interfaces can be used to leverage the lambda expression capability of Java 8. For example, ‘List’ or ‘Collection’ interfaces do not have ‘forEach’ method declaration. Thus, adding such method will simply break the collection framework implementations. Java 8 introduces default method so that List/Collection interface can have a default implementation of forEach method, and the class implementing these interfaces need not implement the same.

public interface vehicle {
  default void print(){
      System.out.println("I am a vehicle!");
                       }
                          }
Ashish Saini
  • 2,328
  • 25
  • 21