Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are Java 8 lambdas compiled as inner classes, methods or something else? [duplicate]

I have read this article today regarding lambdas:

http://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood

The article suggests, that lambdas are not implemented as anon inner classes (due to performance). It gives an example that a lambda expression can be compiled as a (static) method of class.

I have tried a very simple snippet:

private void run() {
    System.out.println(this);
    giveHello(System.out::println);
}

private void giveHello(Consumer<String> consumer) {
    System.out.println(consumer);
    consumer.accept("hello");
}

and the output is :

sample.Main@14ae5a5
sample.Main$$Lambda$1/168423058@4a574795
hello

So it's not the same instance. It's not some central "Lambda Factory" instance either..

How are lambdas implemented then?

like image 206
Yanko Avatar asked Oct 08 '14 12:10

Yanko


People also ask

Does Java 8 have lambdas?

Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.

Which of these statements are true for lambda expressions in Java 8?

Q 5 - Which of the following is correct about Java 8 lambda expression? A - Lambda expressions are used primarily to define inline implementation of a functional interface. B - Lambda expression eliminates the need of anonymous class and gives a very simple yet powerful functional programming capability to Java.

What are the characteristics of a Java 8 lambda expression?

Characteristics of Lambda ExpressionOptional Type Declaration − There is no need to declare the type of a parameter. The compiler inferences the same from the value of the parameter. Optional Parenthesis around Parameter − There is no need to declare a single parameter in parenthesis.

What do you get if you compile a lambda in Java?

The value of a lambda expression is a reference to an instance of a class with the following properties: The class implements the targeted functional interface and, if the target type is an intersection type, every other interface element of the intersection.


2 Answers

The expression itself, assuming you pass an actual lambda expression and not a method reference, is compiled as a separate, synthetic method. In addition to any formal arguments to the expected functional interface (e.g., a single String in the case of Consumer<String>), it will include arguments for any captured values.

At the code location where a lambda expression or method reference appears, an invokedynamic instruction is emitted. The first time this instruction is hit, a call is made into a bootstrap method on LambdaMetafactory. This bootstrap method will fix up an actual implementation of the target functional interface which delegates to the target method, and this is what gets returned. The target method is either the synthetic method representing the lambda body or whichever named method was provided using the :: operator. While a class that implements the functional interface is being created, the process is deferred; it does not happen at compile time.

Finally, the runtime patches the invokedynamic site with the bootstrap result1, which is effectively a constructor call to the generated delegate with any captured values passed in, including (possibly) an invocation target2. This alleviates the performance hit by removing the bootstrapping process for subsequent calls.


1 See java.lang.invoke end of chapter "timing of linkage", courtesy of @Holger.

2 In the case of a lambda which no captures, the invokedynamic instruction will usually resolve to a shared delegate instance that can be reused during subsequent calls, though this is an implementation detail.

like image 58
Mike Strobel Avatar answered Sep 28 '22 00:09

Mike Strobel


I asked myself the same question and found this video, a talk by Brian Goetz. It is very useful introduction to how lambdas are implemented in java.

Edit (summary): Watched it a while back, so this might not be completely correct. When the files are compiled, the compiler leaves a description of what the lambda should do. The JRE, then when running the code, will then decide how to implement the lambda. There are several options, inline, method reference, anonymous class. It will then use dynamic allocation to allocate the implementation.

like image 29
PeterK Avatar answered Sep 27 '22 23:09

PeterK