Java lambda函数将如何编译?

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();

那么它会替代(某种内联),还是实际上创建一个匿名类?

回答:

VM决定如何实现lambda,而不是编译器。

请参阅《 Lambda表达式的翻译》中的Translation strategy部分。

我们没有生成字节码来创建实现lambda表达式的对象(例如,调用内部类的构造函数),而是描述了构造lambda的方法,并将实际构造委托给语言运行时。该配方被编码在invokedynamic指令的静态和动态参数列表中。

for 就简单的编译或性能而言,从你的示例中进行构造是最有效的方法(但根据测试,性能差异很小)。

插件:

我创建并分解了两个示例:

for (String string: Arrays.asList("hello")) {

System.out.println(string);

}

反汇编的字节码,常量和其他信息:

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);});

反汇编的字节码,常量和其他信息:

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对1262b)。

以上是 Java lambda函数将如何编译? 的全部内容, 来源链接: utcz.com/qa/402881.html

回到顶部