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?
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.
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.
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.
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.
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.
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.
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