内存如何分配给lambda |它是如何通过非超类引用变量引用的 [英] How Memory assigns to lambda | How does it refered,by non super class reference variable

查看:150
本文介绍了内存如何分配给lambda |它是如何通过非超类引用变量引用的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建功能界面的实现,下面是我的代码

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆