Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will code containing lambda expressions run on an older JVM, say, for java 1.6? [duplicate]

Tags:

Lambdas were introduced in Java8. Will code containing lambda expressions run on an older JVM, say, for java 1.6? I am concerned about binary compatibility not source code compatibility. It is a simple Yes/No question.

Thanks.

like image 942
user674669 Avatar asked Apr 23 '17 07:04

user674669


People also ask

How is lambda expression represented by JVM?

For Lambda expressions, the compiler doesn't translate them into something which is already understood by JVM. Lambda syntax that is written by the developer is desugared into JVM level instructions generated during compilation, which means the actual responsibility of constructing lambda is deferred to runtime.

Does Java 11 support lambda expressions?

From Java 11 var can also be used for lambda parameter types. Here is an example of using the Java var keyword as parameter types in a lambda expression: Function<String, String> toLowerCase = (var input) -> input.

What difference does lambda make in memory and processing from JVM perspective?

Lambdas make your code less verbose, easier to understand, and "easier" to parallelise. And thats what you should care about.

Which version of Java is lambda?

Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value.


2 Answers

Oracle tries very hard to keep the Java language and the JVM bytecode language separate. The Java Language Specification only says what a program that contains a lambda expression means, it doesn't say anything about how this program is supposed to be compiled or interpreted.

This means specifically that there is nothing in the Java Language Specification that forbids that lambda expressions are compiled in such a way that the resulting code can be executed by a Java 6 JVM, but there is nothing in the Java Language Specification that guarantees it either. Every Java vendor is allowed to encode lambda expressions in whatever way they want. (Obviously, for pragmatic reasons, most try to match whatever Oracle does pretty closely. That way, for example, debuggers / de-compilers / tools which can understand and reverse-engineer lambdas encoded by Oracle's javac will automatically work with bytecode produced by IBM J9 JDK's Java compiler.)

The javac compiler which ships with the Oracle JDK encodes lambda expressions using a rather complicated machinery of LambdaMetafactory, MethodHandles, and invokedynamic. The latter was only introduced in the Java 7 JVM, so this means that the specific encoding that Oracles JDK's javac uses requires at least a Java 7 JVM. But other encodings are definitely possible, none of this complex machinery is truly necessary, it is just a performance optimization. You could e.g. encode Lambda Expressions as inner classes, which would work down to the Java 1.1 JVM – this is after all exactly how we have written "poor man's lambdas" up to Java 8; it's also how original proposals for lambdas and even early previews of Java 8 implemented it, after all, the development of lambdas in Java pre-dates even Java 7 and invokedynamic.

There is a compiler called RetroLambda, which compiles Java 8 JVM bytecode (not Java source code!) produced by Oracle JDK javac to Java 7 JVM bytecode, Java 6 JVM bytecode, or Java 5 JVM bytecode. Using this compiler, you can produce a class file containing bytecode that will run on any Java 5 or newer JVM from Java 8 source code that uses (almost) all features of Java 8.

like image 117
Jörg W Mittag Avatar answered Oct 09 '22 07:10

Jörg W Mittag


Short answer: it depends.

If you are completely restricted to Oracle javac and libraries, the answer is: no; for the following reasons.

Java bytecode contains a major version number. By default, a Java 8 compiler puts java8 into the data. Any older JVM simply refuses to run that code. It is possible though to tell a Java 8 compiler to create bytecode compatible to older JVMs. But: in order for the older JVM to execute such "special" class files, you need all its dependencies to be available!

And there it breaks: Lambdas make use of the invokedynamic bytecode instruction which doesn't exist in Java 6. And beyond that, the compiler makes use of a large number of Java library stuff when compiling lambdas - all of them added after java 6.

So even when you would manage to compile lambda using source code to Java 6 bytecode - that instruction isn't available,and you need to provide all those other classes, too.

But: as the other great answer explains, there are alternatives to javac which allow you to use lambdas on older JVMs.

But: be careful how to spend your energy. Java 6 is still dead for "server side java". So using these alternatives is OK for platforms like Android, but when you are still running an Oracle Java 6 JVM somewhere, you should rather spend your energy on upgrading that system to a current version of Java.

like image 33
GhostCat Avatar answered Oct 09 '22 08:10

GhostCat