内存如何分配给lambda |它是如何通过非超类引用变量引用的 [英] How Memory assigns to lambda | How does it refered,by non super class reference variable
问题描述
我正在创建功能界面的实现,下面是我的代码
Consumer< Integer> consumer = new Consumer< Integer>(){
@Override
public void accept(Integer t){
System.out.println(t);
}
};
根据 javadoc
类类型T的变量可以将空引用或引用
保存到类T的实例或T的子类的任何类的实例。
这里创建了匿名对象的对象,它是 Consumer
的子类,可以通过引用变量引用 consumer
,这很好。
但是我看到消费者
是 FunctionalInterface
,所以我也可以在java8中做这样的事情 -
使用Lambda
消费者<整数>消费者= T->的System.out.println(T);
或使用方法参考
消费者<整数>消费= System.out中::的println;
我知道在上述两种情况下都没有创建子类或匿名类。所以这导致我两个混乱 -
1:如果这里消费者
不是指子类或<$ class的匿名类c $ c>消费者,所以不违反上述概念变量只能引用child / self或 null
?
2:内存如何分配给lamdas以及JVM在运行时如何处理?
您需要参考SE8 15.27:
15.27.3。 Lambda表达式的类型
如果T是一个函数,则lambda表达式在赋值上下文,调用
上下文或具有目标类型T的转换上下文中是兼容的
接口类型(§9.8),表达式与从T派生的地面目标类型的
函数类型一致。
运行时处理使用 invokedynamic
来处理棘手的事情。让我们检查一些代码:
import java.util.function。*;
类R实现Runnable {
public void run(){System.out.println(there); }
}
公共类L {
public static void execute(Runnable r){
System.out.println(r.getClass());
r.run();
}
public static void main(String [] a){
execute(new R()); // subclass
execute(new Runnable(){//匿名子类
public void run(){System.out.println(others);}
});
execute(() - > System.out.println(here)); // lambda
}
}
执行给出:
> java L
class R
有
class L $ 1
其他地方
class L $$ Lambda $ 1/791452441
这里
对于前两个,毫无疑问,方法收到的对象的类执行
是(按给定顺序) R
( Runnable
的子类型), L $ 1
(匿名子类型
L $$ Lambda $ 1/791452441
(从lambda运行时构造的 Runnable
的子类型。请注意,在lambda的情况下,没有 .class
file,该类型在运行时由特殊构造构造。让我们检查字节码:
> javap -c -v L
Classfile /private/tmp/L.class
最后修改1août2017;大小1234字节
MD5校验和9680a2bc143d25344979bae00fff3db7
编译自L.java
公共课L
次要版本:0
主要版本:52
标志:ACC_PUBLIC,ACC_SUPER
常数po ol:
#1 = Methodref#15。#28 // java / lang / Object。< init>:()V
#2 = Fieldref#29.#30 // java /朗/ System.out的:Ljava / IO /的PrintStream;
#3 = Methodref#15。#31 // java / lang / Object.getClass :()Ljava / lang / Class;
#4 = Methodref#32。#33 // java / io / PrintStream.println:(Ljava / lang / Object;)V
#5 = InterfaceMethodref#34。#35 // java / lang /Runnable.run:()V
#6 = Class#36 // R
#7 = Methodref#6。#28 // R。< init>:()V
#8 = Methodref#14。#37 // L.execute:(Ljava / lang / Runnable;)V
#9 = Class#38 // L $ 1
#10 = Methodref#9 。#28 // L $ 1.< init>:()V
#11 = InvokeDynamic#0:#43 //#0:run :()Ljava / lang / Runnable;
#12 =字符串#44 //这里
#13 = Methodref#32。#java // java / io / PrintStream.println:(Ljava / lang / String;)V
# 14 = Class#46 // L
#15 = Class#47 // java / lang / Object
#16 = Utf8 InnerClasses
#17 = Utf8< init>
#18 = Utf8()V
#19 = Utf8代码
#20 = Utf8 LineNumberTable
#21 = Utf8执行
#22 = Utf8(Ljava / lang / runnable;)V
#23 = Utf8 main
#24 = Utf8([Ljava / lang / String;)V
#25 = Utf8 lambda $ main $ 0
#26 = Utf8 SourceFile
#27 = Utf8 L.java
#28 = NameAndType#17:#18 //< init>:()V
#29 = Class#48 / / java / lang / System
#30 = NameAndType#49:#50 // out:Ljava / io / PrintStream;
#31 = NameAndType#51:#52 // getClass :()Ljava / lang / Class;
#32 = Class#53 // java / io / PrintStream
#33 = NameAndType#54:#55 // println:(Ljava / lang / Object;)V
#34 = Class#56 // java / lang / Runnable
#35 = NameAndType#57:#18 // run :()V
#36 = Utf8 R
#37 = NameAndType#21: #22 //执行:(Ljava / lang / Runnable;)V
#38 = Utf8 L $ 1
#39 = Utf8 BootstrapMethods
#40 = MethodHandle#6:#58 // invokestatic的java /郎/调用/ LambdaMetafactory.metafactory:(Ljava /郎/调用/ MethodHandles $查找; Ljava /郎/字符串; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodHandle ; Ljava /郎/调用/ MethodType;)Ljava /郎/调用/调用点;
#41 = MethodType#18 //()V
#42 = MethodHandle#6:#59 // invokestatic L.lambda $ main $ 0 :()V
#43 = NameAndType# 57:#60 //运行:()Ljava / lang / Runnable;
#44 = Utf8这里
#45 = NameAndType#54:#61 // println:(Ljava / lang / String;)V
#46 = Utf8 L
#47 = Utf8 java / lang / Object
#48 = Utf8 java / lang / System
#49 = Utf8 out
#50 = Utf8 Ljava / io / PrintStream;
#51 = Utf8 getClass
#52 = Utf8()Ljava / lang / Class;
#53 = Utf8 java / io / PrintStream
#54 = Utf8 println
#55 = Utf8(Ljava / lang / Object;)V
#56 = Utf8 java / lang / runnable
#57 = Utf8运行
#58 = Methodref#62。#63 // java / lang / invoke / LambdaMetafactory.metafactory :( Ljava / lang / invoke / MethodHandles $ Lookup; Ljava / lang /字符串; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodHandle; Ljava /郎/调用/ MethodType;)Ljava /郎/调用/调用点;
#59 = Methodref#14。#64 // L.lambda $ main $ 0 :()V
#60 = Utf8()Ljava / lang / Runnable;
#61 = Utf8(Ljava / lang / String;)V
#62 = Class#65 // java / lang / invoke / LambdaMetafactory
#63 = NameAndType#66:#69 / / 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 /郎/调用/调用点;
#64 = NameAndType#25:#18 // lambda $ main $ 0 :()V
#65 = Utf8 java / lang / invoke / LambdaMetafactory
#66 = Utf8 metafactory
#67 = Class#71 // java / lang / invoke / MethodHandles $ Lookup
#68 = Utf8 Lookup
#69 = Utf8(Ljava / lang / invoke / MethodHandles $ Lookup; Ljava / lang /字符串; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodHandle; Ljava /郎/调用/ MethodType;)Ljava /郎/调用/调用点;
#70 =类#72 // java / lang / invoke / MethodHandles
#71 = Utf8 java / lang / invoke / MethodHandles $ Lookup
#72 = Utf8 java / lang / invoke / MethodHandles
{
public L();
描述符:()V
标志:ACC_PUBLIC
代码:
stack = 1,locals = 1,args_size = 1
0:aload_0
1: invokespecial#1 //方法java / lang / Object。< init>:()V
4:返回
LineNumberTable:
第9行:0
public static void execute(java.lang.Runnable);
描述符:(Ljava / lang / Runnable;)V
标志:ACC_PUBLIC,ACC_STATIC
代码:
stack = 2,locals = 1,args_size = 1
0 :getstatic#2 // Field java / lang / System.out:Ljava / io / PrintStream;
3:aload_0
4:invokevirtual#3 //方法java / lang / Object.getClass :()Ljava / lang / Class;
7:invokevirtual#4 //方法java / io / PrintStream.println:(Ljava / lang / Object;)V
10:aload_0
11:invokeinterface#5,1 // InterfaceMethod java / lang / Runnable.run :()V
16:返回
LineNumberTable:
第11行:0
第12行:10
第13行:16
public static void main(java.lang.String []);
描述符:([Ljava / lang / String;)V
标志:ACC_PUBLIC,ACC_STATIC
代码:
stack = 2,locals = 1,args_size = 1
0:new#6 // class R
3:dup
4:invokespecial#7 // Method R。< init>:()V
7:invokestatic#8 / /方法执行:(Ljava / lang / Runnable;)V
10:new#9 // class L $ 1
13:dup
14:invokespecial#10 // Method L $ 1。 < init>:()V
17:invokestatic#8 //方法执行:(Ljava / lang / Runnable;)V
20:invokedynamic#11,0 // InvokeDynamic#0:运行:()Ljava /郎/可运行;
25:invokestatic#8 //方法执行:(Ljava / lang / Runnable;)V
28:返回
LineNumberTable:
第15行:0
第16行:10
第19:20
第20行:28
}
SourceFile:L.java
InnerClasses:
static#9; // class L $ 1
public static final#68 =#70的#67; // Lookup = class java / lang / invoke / MethodHandles $查找类java / lang / invoke / MethodHandles
BootstrapMethods:
0:#40 invokestatic java / lang / invoke / LambdaMetafactory.metafactory:(Ljava /郎/调用/ MethodHandles $查找; Ljava /郎/字符串; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodHandle; Ljava /郎/调用/ MethodType;)Ljava /朗/调用/调用点;
方法参数:
#41()V
#42 invokestatic L.lambda $ main $ 0 :()V
#41()V
第一个有趣的部分是 main
的代码:
public static void main(java.lang.String []);
描述符:([Ljava / lang / String;)V
标志:ACC_PUBLIC,ACC_STATIC
代码:
stack = 2,locals = 1,args_size = 1
0:new#6 // class R
3:dup
4:invokespecial#7 // Method R。< init>:()V
7:invokestatic#8 / /方法执行:(Ljava / lang / Runnable;)V
10:new#9 // class L $ 1
13:dup
14:invokespecial#10 // Method L $ 1。 < init>:()V
17:invokestatic#8 //方法执行:(Ljava / lang / Runnable;)V
20:invokedynamic#11,0 // InvokeDynamic#0:运行:()Ljava /郎/可运行;
25:invokestatic#8 //方法执行:(Ljava / lang / Runnable;)V
28:返回
正如您所看到的,界面的显式实现或匿名实现之间没有区别。最后一个只涉及类命名技巧( L $ 1
),但两者都以相同的方式使用,通过 invokestatic
。 / p>
有趣的案例是第三个(lambda one)涉及 invokedynamic
然后 invokestatic
。请注意, invokestatic
调用与前两个调用相同的方法(方法 run
)。
粗略地说,第一次调用 invokedynamic
时,调用bootstrap方法来构造 CallSite
(参见 Java中的CallSite API )然后将进一步用于执行lambda的代码。请参阅此处的bootstrap调用:
BootstrapMethods:
0:#40 invokestatic java / lang / invoke / LambdaMetafactory.metafactory :(Ljava /郎/调用/ MethodHandles $查找; Ljava /郎/字符串; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodType; Ljava /郎/调用/ MethodHandle; Ljava /郎/调用/ MethodType; )Ljava /郎/调用/调用点;
方法参数:
#41()V
#42 invokestatic L.lambda $ main $ 0 :()V
#41()V
以及致电网站推荐的代码:
#41 = MethodType#18 //()V
#42 = MethodHandle#6:#59 // invokestatic L.lambda $ main $ 0 :()V
#43 = NameAndType# 57:#60 //运行:()Ljava / lang / Runnable;
#44 = Utf8这里
#45 = NameAndType#54:#61 // println:(Ljava / lang / String;)V
#46 = Utf8 L
#47 = Utf8 java / lang / Object
#48 = Utf8 java / lang / System
#49 = Utf8 out
#50 = Utf8 Ljava / io / PrintStream;
#51 = Utf8 getClass
#52 = Utf8()Ljava / lang / Class;
#53 = Utf8 java / io / PrintStream
#54 = Utf8 println
#55 = Utf8(Ljava / lang / Object;)V
#56 = Utf8 java / lang / Runnable
#57 = Utf8运行
I was creating the implementation of functional interface,below is my code
Consumer<Integer> consumer=new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(t);
}
};
As per javadoc
A variable of a class type T can hold a null reference or a reference to an instance of class T or of any class that is a subclass of T.
Here Object of anonymous object created,which is subclass of Consumer
and can be refer by reference variable consumer
,which is Fine.
But I saw Consumer
is FunctionalInterface
,so I can also do something like this in java8-
Using Lambda
Consumer<Integer> consumer=t->System.out.println(t);
OR Using Method Reference
Consumer<Integer> consumer=System.out::println;
What I knows no sub classes or Anonymous classes being created in both the above cases.So this results me two confusion-
1 : If here consumer
is not referring to subclass or Anonymous class of Consumer
,so isn't this violating the above mentioned concept variable can only refer child/self or null
?
2 : How memory assign to lamdas and how does JVM handle such at run time?
You need to refer to SE8 15.27:
15.27.3. Type of a Lambda Expression
A lambda expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.
Runtime handling use tricky things with invokedynamic
. Let examine some code:
import java.util.function.*;
class R implements Runnable {
public void run() { System.out.println("there"); }
}
public class L {
public static void execute(Runnable r) {
System.out.println(r.getClass());
r.run();
}
public static void main(String []a) {
execute(new R()); // subclass
execute(new Runnable() { // anonymous subclass
public void run() { System.out.println("elsewhere"); }
});
execute(() -> System.out.println("here")); // lambda
}
}
Execution gives:
> java L
class R
there
class L$1
elsewhere
class L$$Lambda$1/791452441
here
For the first two there is no surprise, the class of the object received by method execute
is (in the given order) R
(the subtype of Runnable
), L$1
(the anonymous subtype of Runnable
, and L$$Lambda$1/791452441
(the subtype of Runnable
constructed at run time from the lambda). Note that in the case of lambda there is no .class
file, the type is constructed at runtime by special construct. Let's examine the bytecode:
> javap -c -v L
Classfile /private/tmp/L.class
Last modified 1 août 2017; size 1234 bytes
MD5 checksum 9680a2bc143d25344979bae00fff3db7
Compiled from "L.java"
public class L
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #15.#28 // java/lang/Object."<init>":()V
#2 = Fieldref #29.#30 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Methodref #15.#31 // java/lang/Object.getClass:()Ljava/lang/Class;
#4 = Methodref #32.#33 // java/io/PrintStream.println:(Ljava/lang/Object;)V
#5 = InterfaceMethodref #34.#35 // java/lang/Runnable.run:()V
#6 = Class #36 // R
#7 = Methodref #6.#28 // R."<init>":()V
#8 = Methodref #14.#37 // L.execute:(Ljava/lang/Runnable;)V
#9 = Class #38 // L$1
#10 = Methodref #9.#28 // L$1."<init>":()V
#11 = InvokeDynamic #0:#43 // #0:run:()Ljava/lang/Runnable;
#12 = String #44 // here
#13 = Methodref #32.#45 // java/io/PrintStream.println:(Ljava/lang/String;)V
#14 = Class #46 // L
#15 = Class #47 // java/lang/Object
#16 = Utf8 InnerClasses
#17 = Utf8 <init>
#18 = Utf8 ()V
#19 = Utf8 Code
#20 = Utf8 LineNumberTable
#21 = Utf8 execute
#22 = Utf8 (Ljava/lang/Runnable;)V
#23 = Utf8 main
#24 = Utf8 ([Ljava/lang/String;)V
#25 = Utf8 lambda$main$0
#26 = Utf8 SourceFile
#27 = Utf8 L.java
#28 = NameAndType #17:#18 // "<init>":()V
#29 = Class #48 // java/lang/System
#30 = NameAndType #49:#50 // out:Ljava/io/PrintStream;
#31 = NameAndType #51:#52 // getClass:()Ljava/lang/Class;
#32 = Class #53 // java/io/PrintStream
#33 = NameAndType #54:#55 // println:(Ljava/lang/Object;)V
#34 = Class #56 // java/lang/Runnable
#35 = NameAndType #57:#18 // run:()V
#36 = Utf8 R
#37 = NameAndType #21:#22 // execute:(Ljava/lang/Runnable;)V
#38 = Utf8 L$1
#39 = Utf8 BootstrapMethods
#40 = MethodHandle #6:#58 // 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;
#41 = MethodType #18 // ()V
#42 = MethodHandle #6:#59 // invokestatic L.lambda$main$0:()V
#43 = NameAndType #57:#60 // run:()Ljava/lang/Runnable;
#44 = Utf8 here
#45 = NameAndType #54:#61 // println:(Ljava/lang/String;)V
#46 = Utf8 L
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 getClass
#52 = Utf8 ()Ljava/lang/Class;
#53 = Utf8 java/io/PrintStream
#54 = Utf8 println
#55 = Utf8 (Ljava/lang/Object;)V
#56 = Utf8 java/lang/Runnable
#57 = Utf8 run
#58 = Methodref #62.#63 // 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;
#59 = Methodref #14.#64 // L.lambda$main$0:()V
#60 = Utf8 ()Ljava/lang/Runnable;
#61 = Utf8 (Ljava/lang/String;)V
#62 = Class #65 // java/lang/invoke/LambdaMetafactory
#63 = NameAndType #66:#69 // 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 = NameAndType #25:#18 // lambda$main$0:()V
#65 = Utf8 java/lang/invoke/LambdaMetafactory
#66 = Utf8 metafactory
#67 = Class #71 // java/lang/invoke/MethodHandles$Lookup
#68 = Utf8 Lookup
#69 = 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;
#70 = Class #72 // java/lang/invoke/MethodHandles
#71 = Utf8 java/lang/invoke/MethodHandles$Lookup
#72 = Utf8 java/lang/invoke/MethodHandles
{
public L();
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 9: 0
public static void execute(java.lang.Runnable);
descriptor: (Ljava/lang/Runnable;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokevirtual #3 // Method java/lang/Object.getClass:()Ljava/lang/Class;
7: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
10: aload_0
11: invokeinterface #5, 1 // InterfaceMethod java/lang/Runnable.run:()V
16: return
LineNumberTable:
line 11: 0
line 12: 10
line 13: 16
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: new #6 // class R
3: dup
4: invokespecial #7 // Method R."<init>":()V
7: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
10: new #9 // class L$1
13: dup
14: invokespecial #10 // Method L$1."<init>":()V
17: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
20: invokedynamic #11, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
25: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
28: return
LineNumberTable:
line 15: 0
line 16: 10
line 19: 20
line 20: 28
}
SourceFile: "L.java"
InnerClasses:
static #9; //class L$1
public static final #68= #67 of #70; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles
BootstrapMethods:
0: #40 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:
#41 ()V
#42 invokestatic L.lambda$main$0:()V
#41 ()V
The first interesting part is the code of main
:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: new #6 // class R
3: dup
4: invokespecial #7 // Method R."<init>":()V
7: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
10: new #9 // class L$1
13: dup
14: invokespecial #10 // Method L$1."<init>":()V
17: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
20: invokedynamic #11, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
25: invokestatic #8 // Method execute:(Ljava/lang/Runnable;)V
28: return
As you can observe there is no difference in between the explicit implementation of the interface or the anonymous one. The last only involves class naming trickery (L$1
), but both are used the same way, through invokestatic
.
Interesting case is the third (the lambda one) which involves invokedynamic
and then invokestatic
. Note that the invokestatic
calls the same method as in the two previous calls (the method run
).
Roughly, the first time the invokedynamic
is called a bootstrap method is called to construct a CallSite
(see CallSite in Java API) which will then be used further to execute the code of the lambda. See the bootstrap call here:
BootstrapMethods:
0: #40 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:
#41 ()V
#42 invokestatic L.lambda$main$0:()V
#41 ()V
and the code referred by the call site:
#41 = MethodType #18 // ()V
#42 = MethodHandle #6:#59 // invokestatic L.lambda$main$0:()V
#43 = NameAndType #57:#60 // run:()Ljava/lang/Runnable;
#44 = Utf8 here
#45 = NameAndType #54:#61 // println:(Ljava/lang/String;)V
#46 = Utf8 L
#47 = Utf8 java/lang/Object
#48 = Utf8 java/lang/System
#49 = Utf8 out
#50 = Utf8 Ljava/io/PrintStream;
#51 = Utf8 getClass
#52 = Utf8 ()Ljava/lang/Class;
#53 = Utf8 java/io/PrintStream
#54 = Utf8 println
#55 = Utf8 (Ljava/lang/Object;)V
#56 = Utf8 java/lang/Runnable
#57 = Utf8 run
这篇关于内存如何分配给lambda |它是如何通过非超类引用变量引用的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!