No, lambda doesn't creates inline blocks in the byte code.
See Java Language Specification: 15.27.4. Run-Time Evaluation of Lambda Expressions
At run time, evaluation of a lambda expression is similar to
evaluation of a class instance creation expression, insofar as normal
completion produces a reference to an object. Evaluation of a lambda
expression is distinct from execution of the lambda body.
Here is a simple test program to see what byte code is created.
For this we have an interface and a simple main class.
Block.java
@FunctionalInterface
public interface Block<T> {
T apply() throws Exception;
}
Main.java
public class Main {
public static void main(String[] args) throws Exception {
String foobar = func(() -> "Hello World");
System.out.println(foobar);
}
final static <T> T func(final Block<T> b) throws Exception {
return b.apply();
}
}
Compile it, now you can use javap
to view the bytecode:
javap -verbose Block.class
prints:
Classfile Block.class
Last modified 11.12.2017; size 331 bytes
MD5 checksum d6e4627f60a7cb24b7f23064c156ede6
Compiled from "Block.java"
public interface Block<T extends java.lang.Object>
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
#1 = Class #2 // Block
#2 = Utf8 Block
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 apply
#6 = Utf8 ()Ljava/lang/Object;
#7 = Utf8 Exceptions
#8 = Class #9 // java/lang/Exception
#9 = Utf8 java/lang/Exception
#10 = Utf8 Signature
#11 = Utf8 ()TT;
#12 = Utf8 SourceFile
#13 = Utf8 Block.java
#14 = Utf8 <T:Ljava/lang/Object;>Ljava/lang/Object;
#15 = Utf8 RuntimeVisibleAnnotations
#16 = Utf8 Ljava/lang/FunctionalInterface;
{
public abstract T apply() throws java.lang.Exception;
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC, ACC_ABSTRACT
Exceptions:
throws java.lang.Exception
Signature: #11 // ()TT;
}
SourceFile: "Block.java"
Signature: #14 // <T:Ljava/lang/Object;>Ljava/lang/Object;
RuntimeVisibleAnnotations:
0: #16()
javap -verbose Main.class
prints:
Classfile Main.class
Last modified 11.12.2017; size 1512 bytes
MD5 checksum 73ceb403dfcecbf4dbb5e03ec2fe852d
Compiled from "Main.java"
public class Main
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #2 // Main
#2 = Utf8 Main
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Methodref #3.#9 // java/lang/Object."<init>":()V
#9 = NameAndType #5:#6 // "<init>":()V
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 LMain;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = Utf8 Exceptions
#17 = Class #18 // java/lang/Exception
#18 = Utf8 java/lang/Exception
#19 = NameAndType #20:#21 // apply:()LBlock;
#20 = Utf8 apply
#21 = Utf8 ()LBlock;
#22 = InvokeDynamic #0:#19 // #0:apply:()LBlock;
#23 = Methodref #1.#24 // Main.func:(LBlock;)Ljava/lang/Object;
#24 = NameAndType #25:#26 // func:(LBlock;)Ljava/lang/Object;
#25 = Utf8 func
#26 = Utf8 (LBlock;)Ljava/lang/Object;
#27 = Class #28 // java/lang/String
#28 = Utf8 java/lang/String
#29 = Fieldref #30.#32 // java/lang/System.out:Ljava/io/PrintStream;
#30 = Class #31 // java/lang/System
#31 = Utf8 java/lang/System
#32 = NameAndType #33:#34 // out:Ljava/io/PrintStream;
#33 = Utf8 out
#34 = Utf8 Ljava/io/PrintStream;
#35 = Methodref #36.#38 // java/io/PrintStream.println:(Ljava/lang/String;)V
#36 = Class #37 // java/io/PrintStream
#37 = Utf8 java/io/PrintStream
#38 = NameAndType #39:#40 // println:(Ljava/lang/String;)V
#39 = Utf8 println
#40 = Utf8 (Ljava/lang/String;)V
#41 = Utf8 args
#42 = Utf8 [Ljava/lang/String;
#43 = Utf8 foobar
#44 = Utf8 Ljava/lang/String;
#45 = Utf8 Signature
#46 = Utf8 <T:Ljava/lang/Object;>(LBlock<TT;>;)TT;
#47 = InterfaceMethodref #48.#50 // Block.apply:()Ljava/lang/Object;
#48 = Class #49 // Block
#49 = Utf8 Block
#50 = NameAndType #20:#51 // apply:()Ljava/lang/Object;
#51 = Utf8 ()Ljava/lang/Object;
#52 = Utf8 b
#53 = Utf8 LBlock;
#54 = Utf8 LocalVariableTypeTable
#55 = Utf8 LBlock<TT;>;
#56 = Utf8 lambda$0
#57 = Utf8 ()Ljava/lang/String;
#58 = String #59 // Hello World
#59 = Utf8 Hello World
#60 = Utf8 SourceFile
#61 = Utf8 Main.java
#62 = Utf8 BootstrapMethods
#63 = Methodref #64.#66 // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#64 = Class #65 // java/lang/invoke/LambdaMetafactory
#65 = Utf8 java/lang/invoke/LambdaMetafactory
#66 = NameAndType #67:#68 // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#67 = Utf8 metafactory
#68 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#69 = MethodHandle #6:#63 // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#70 = MethodType #51 // ()Ljava/lang/Object;
#71 = Methodref #1.#72 // Main.lambda$0:()Ljava/lang/String;
#72 = NameAndType #56:#57 // lambda$0:()Ljava/lang/String;
#73 = MethodHandle #6:#71 // invokestatic Main.lambda$0:()Ljava/lang/String;
#74 = MethodType #57 // ()Ljava/lang/String;
#75 = Utf8 InnerClasses
#76 = Class #77 // java/lang/invoke/MethodHandles$Lookup
#77 = Utf8 java/lang/invoke/MethodHandles$Lookup
#78 = Class #79 // java/lang/invoke/MethodHandles
#79 = Utf8 java/lang/invoke/MethodHandles
#80 = Utf8 Lookup
{
public Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 2: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LMain;
public static void main(java.lang.String[]) throws java.lang.Exception;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Exceptions:
throws java.lang.Exception
Code:
stack=2, locals=2, args_size=1
0: invokedynamic #22, 0 // InvokeDynamic #0:apply:()LBlock;
5: invokestatic #23 // Method func:(LBlock;)Ljava/lang/Object;
8: checkcast #27 // class java/lang/String
11: astore_1
12: getstatic #29 // Field java/lang/System.out:Ljava/io/PrintStream;
15: aload_1
16: invokevirtual #35 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
19: return
LineNumberTable:
line 4: 0
line 5: 12
line 6: 19
LocalVariableTable:
Start Length Slot Name Signature
0 20 0 args [Ljava/lang/String;
12 8 1 foobar Ljava/lang/String;
static final <T extends java.lang.Object> T func(Block<T>) throws java.lang.Exception;
descriptor: (LBlock;)Ljava/lang/Object;
flags: ACC_STATIC, ACC_FINAL
Exceptions:
throws java.lang.Exception
Signature: #46 // <T:Ljava/lang/Object;>(LBlock<TT;>;)TT;
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokeinterface #47, 1 // InterfaceMethod Block.apply:()Ljava/lang/Object;
6: areturn
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 7 0 b LBlock;
LocalVariableTypeTable:
Start Length Slot Name Signature
0 7 0 b LBlock<TT;>;
}
SourceFile: "Main.java"
BootstrapMethods:
0: #69 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#70 ()Ljava/lang/Object;
#73 invokestatic Main.lambda$0:()Ljava/lang/String;
#74 ()Ljava/lang/String;
InnerClasses:
public static final #80= #76 of #78; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
You can see that for the lambda it creates a
#73 invokestatic Main.lambda$0:()Ljava/lang/String;
also the block is called with
#22 = InvokeDynamic #0:#19 // #0:apply:()LBlock;