如何编译Java lambda函数? [英] How will Java lambda functions be compiled?
问题描述
Loop.times(5, () -> {
System.out.println("looping");
});
它有效编译到哪一个?
for(int i = 0; i < 5; i++)
System.out.println("looping");
或类似的东西
new CallableInterfaceImpl(){
public void call(){
for(int i = 0; i < 5; i++)
System.out.println("looping");
}
}.call();
那么它会替换(内联类型),还是实际创建一个匿名类?
So would it replace (kind of inline), or actually create an anonymous class?
推荐答案
VM决定如何实现lambda,而不是编译器。
The VM decides how to implement lambda, not a compiler.
参见翻译策略
Lambda表达式的翻译。
我们不是生成字节码来创建实现lambda表达式的对象(例如调用内部类的构造函数),而是描述一个用于构造lambda的配方,并将实际构造委托给语言运行库。该配方在invokedynamic指令的静态和动态参数列表中编码。
Instead of generating bytecode to create the object that implements the lambda expression (such as calling a constructor for an inner class), we describe a recipe for constructing the lambda, and delegate the actual construction to the language runtime. That recipe is encoded in the static and dynamic argument lists of an invokedynamic instruction.
for
从简单的编译或性能来看,你的例子中的构造是最有效的方法(但是通过测试,性能差异非常小)。
for
construction from your example is most effective way in terms of simple compiling or perfomance (but the performance differences are very small, by the tests).
插件:
我创建并反汇编了两个例子:
I created and disassemble two examples:
for (String string: Arrays.asList("hello")) {
System.out.println(string);
}
反汇编的字节码,常量和其他信息:
Disassembled bytecode, constants and other information:
Classfile LambdaCode.class
Last modified 30.05.2013; size 771 bytes
MD5 checksum 79bf2821b5a14485934e5cebb60c99d6
Compiled from "LambdaCode.java"
public class test.lambda.LambdaCode
SourceFile: "LambdaCode.java"
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #11.#22 // java/lang/Object."<init>":()V
#2 = Class #23 // java/lang/String
#3 = String #24 // hello
#4 = Methodref #25.#26 // java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
#5 = InterfaceMethodref #27.#28 // java/util/List.iterator:()Ljava/util/Iterator;
#6 = InterfaceMethodref #29.#30 // java/util/Iterator.hasNext:()Z
#7 = InterfaceMethodref #29.#31 // java/util/Iterator.next:()Ljava/lang/Object;
#8 = Fieldref #32.#33 // java/lang/System.out:Ljava/io/PrintStream;
#9 = Methodref #34.#35 // java/io/PrintStream.println:(Ljava/lang/String;)V
#10 = Class #36 // test/lambda/LambdaCode
#11 = Class #37 // java/lang/Object
#12 = Utf8 <init>
#13 = Utf8 ()V
#14 = Utf8 Code
#15 = Utf8 LineNumberTable
#16 = Utf8 main
#17 = Utf8 ([Ljava/lang/String;)V
#18 = Utf8 StackMapTable
#19 = Class #38 // java/util/Iterator
#20 = Utf8 SourceFile
#21 = Utf8 LambdaCode.java
#22 = NameAndType #12:#13 // "<init>":()V
#23 = Utf8 java/lang/String
#24 = Utf8 hello
#25 = Class #39 // java/util/Arrays
#26 = NameAndType #40:#41 // asList:([Ljava/lang/Object;)Ljava/util/List;
#27 = Class #42 // java/util/List
#28 = NameAndType #43:#44 // iterator:()Ljava/util/Iterator;
#29 = Class #38 // java/util/Iterator
#30 = NameAndType #45:#46 // hasNext:()Z
#31 = NameAndType #47:#48 // next:()Ljava/lang/Object;
#32 = Class #49 // java/lang/System
#33 = NameAndType #50:#51 // out:Ljava/io/PrintStream;
#34 = Class #52 // java/io/PrintStream
#35 = NameAndType #53:#54 // println:(Ljava/lang/String;)V
#36 = Utf8 test/lambda/LambdaCode
#37 = Utf8 java/lang/Object
#38 = Utf8 java/util/Iterator
#39 = Utf8 java/util/Arrays
#40 = Utf8 asList
#41 = Utf8 ([Ljava/lang/Object;)Ljava/util/List;
#42 = Utf8 java/util/List
#43 = Utf8 iterator
#44 = Utf8 ()Ljava/util/Iterator;
#45 = Utf8 hasNext
#46 = Utf8 ()Z
#47 = Utf8 next
#48 = Utf8 ()Ljava/lang/Object;
#49 = Utf8 java/lang/System
#50 = Utf8 out
#51 = Utf8 Ljava/io/PrintStream;
#52 = Utf8 java/io/PrintStream
#53 = Utf8 println
#54 = Utf8 (Ljava/lang/String;)V
{
public test.lambda.LambdaCode();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 15: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=3, args_size=1
0: iconst_1
1: anewarray #2 // class java/lang/String
4: dup
5: iconst_0
6: ldc #3 // String hello
8: aastore
9: invokestatic #4 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
12: invokeinterface #5, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
17: astore_1
18: aload_1
19: invokeinterface #6, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
24: ifeq 47
27: aload_1
28: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
33: checkcast #2 // class java/lang/String
36: astore_2
37: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
40: aload_2
41: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
44: goto 18
47: return
LineNumberTable:
line 35: 0
line 36: 37
line 37: 44
line 38: 47
StackMapTable: number_of_entries = 2
frame_type = 252 /* append */
offset_delta = 18
locals = [ class java/util/Iterator ]
frame_type = 250 /* chop */
offset_delta = 28
}
和
Arrays.asList("hello").forEach(p -> {System.out.println(p);});
反汇编的字节码,常量和其他信息:
Disassembled bytecode, constants and other information:
Classfile LambdaCode.class
Last modified 30.05.2013; size 1262 bytes
MD5 checksum 4804e0a37b73141d5791cc39d51d649c
Compiled from "LambdaCode.java"
public class test.lambda.LambdaCode
SourceFile: "LambdaCode.java"
InnerClasses:
public static final #64= #63 of #70; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #27 invokestatic java/lang/invoke/LambdaMetafactory.metaFactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#28 invokeinterface java/util/function/Consumer.accept:(Ljava/lang/Object;)V
#29 invokestatic test/lambda/LambdaCode.lambda$0:(Ljava/lang/String;)V
#30 (Ljava/lang/String;)V
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #10.#21 // java/lang/Object."<init>":()V
#2 = Class #22 // java/lang/String
#3 = String #23 // hello
#4 = Methodref #24.#25 // java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
#5 = InvokeDynamic #0:#31 // #0:lambda$:()Ljava/util/function/Consumer;
#6 = InterfaceMethodref #32.#33 // java/util/List.forEach:(Ljava/util/function/Consumer;)V
#7 = Fieldref #34.#35 // java/lang/System.out:Ljava/io/PrintStream;
#8 = Methodref #36.#37 // java/io/PrintStream.println:(Ljava/lang/String;)V
#9 = Class #38 // test/lambda/LambdaCode
#10 = Class #39 // java/lang/Object
#11 = Utf8 <init>
#12 = Utf8 ()V
#13 = Utf8 Code
#14 = Utf8 LineNumberTable
#15 = Utf8 main
#16 = Utf8 ([Ljava/lang/String;)V
#17 = Utf8 lambda$0
#18 = Utf8 (Ljava/lang/String;)V
#19 = Utf8 SourceFile
#20 = Utf8 LambdaCode.java
#21 = NameAndType #11:#12 // "<init>":()V
#22 = Utf8 java/lang/String
#23 = Utf8 hello
#24 = Class #40 // java/util/Arrays
#25 = NameAndType #41:#42 // asList:([Ljava/lang/Object;)Ljava/util/List;
#26 = Utf8 BootstrapMethods
#27 = MethodHandle #6:#43 // invokestatic java/lang/invoke/LambdaMetafactory.metaFactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#28 = MethodHandle #9:#44 // invokeinterface java/util/function/Consumer.accept:(Ljava/lang/Object;)V
#29 = MethodHandle #6:#45 // invokestatic test/lambda/LambdaCode.lambda$0:(Ljava/lang/String;)V
#30 = MethodType #18 // (Ljava/lang/String;)V
#31 = NameAndType #46:#47 // lambda$:()Ljava/util/function/Consumer;
#32 = Class #48 // java/util/List
#33 = NameAndType #49:#50 // forEach:(Ljava/util/function/Consumer;)V
#34 = Class #51 // java/lang/System
#35 = NameAndType #52:#53 // out:Ljava/io/PrintStream;
#36 = Class #54 // java/io/PrintStream
#37 = NameAndType #55:#18 // println:(Ljava/lang/String;)V
#38 = Utf8 test/lambda/LambdaCode
#39 = Utf8 java/lang/Object
#40 = Utf8 java/util/Arrays
#41 = Utf8 asList
#42 = Utf8 ([Ljava/lang/Object;)Ljava/util/List;
#43 = Methodref #56.#57 // java/lang/invoke/LambdaMetafactory.metaFactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#44 = InterfaceMethodref #58.#59 // java/util/function/Consumer.accept:(Ljava/lang/Object;)V
#45 = Methodref #9.#60 // test/lambda/LambdaCode.lambda$0:(Ljava/lang/String;)V
#46 = Utf8 lambda$
#47 = Utf8 ()Ljava/util/function/Consumer;
#48 = Utf8 java/util/List
#49 = Utf8 forEach
#50 = Utf8 (Ljava/util/function/Consumer;)V
#51 = Utf8 java/lang/System
#52 = Utf8 out
#53 = Utf8 Ljava/io/PrintStream;
#54 = Utf8 java/io/PrintStream
#55 = Utf8 println
#56 = Class #61 // java/lang/invoke/LambdaMetafactory
#57 = NameAndType #62:#66 // metaFactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#58 = Class #67 // java/util/function/Consumer
#59 = NameAndType #68:#69 // accept:(Ljava/lang/Object;)V
#60 = NameAndType #17:#18 // lambda$0:(Ljava/lang/String;)V
#61 = Utf8 java/lang/invoke/LambdaMetafactory
#62 = Utf8 metaFactory
#63 = Class #71 // java/lang/invoke/MethodHandles$Lookup
#64 = Utf8 Lookup
#65 = Utf8 InnerClasses
#66 = Utf8 (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
#67 = Utf8 java/util/function/Consumer
#68 = Utf8 accept
#69 = Utf8 (Ljava/lang/Object;)V
#70 = Class #72 // java/lang/invoke/MethodHandles
#71 = Utf8 java/lang/invoke/MethodHandles$Lookup
#72 = Utf8 java/lang/invoke/MethodHandles
{
public test.lambda.LambdaCode();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 15: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=1, args_size=1
0: iconst_1
1: anewarray #2 // class java/lang/String
4: dup
5: iconst_0
6: ldc #3 // String hello
8: aastore
9: invokestatic #4 // Method java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
12: invokedynamic #5, 0 // InvokeDynamic #0:lambda$:()Ljava/util/function/Consumer;
17: invokeinterface #6, 2 // InterfaceMethod java/util/List.forEach:(Ljava/util/function/Consumer;)V
22: return
LineNumberTable:
line 28: 0
line 38: 22
}
编译器生成的类 - 对于Lambda示例,文件更复杂,更大(771b vs 1262b)。
Compiler generated class-file is more complicated and larger (771b vs 1262b) for Lambda example.
这篇关于如何编译Java lambda函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!