Hotspot invokedynamic指令和Lamada实现原理详解

目录一、Lamada的实现原理1、字节码分析2、调用点限定符3、BootstrapMethods4、CONSTANT_MethodType_info5、CONSTANT_MethodHandle_info6、LambdaMetafactory.metafactory8、InnerClassLambdaMetafactory9、总结二、invokedy...
摘要由CSDN通过智能技术生成

   目录

一、Lamada的实现原理

1、字节码分析

2、调用点限定符

3、BootstrapMethods

4、CONSTANT_MethodType_info 

5、CONSTANT_MethodHandle_info

6、LambdaMetafactory.metafactory

8、InnerClassLambdaMetafactory

9、总结

二、invokedynamic指令

1、使用总结

2、源码解析:


      在上一篇《Hotspot MethodHandle详解》中详细讲解了java.lang.invoke.MethodHandle的背景和使用,这个是invokedynamic指令实现的基础,本篇以Lamada的实现原理为例说明invokedynamic的具体用法以及C++字节码解释器中invokedynamic指令的源码实现。

一、Lamada的实现原理

1、字节码分析

    想看一个典型的Lamada表达式,具体用法可以参考《java8 Lambda表达式》,代码如下:

package jni;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public class LamadaTest {

    public static void main(String[] args) {
        List<String> test= Arrays.asList("a","b","c");
        //完整的写法
//        test.stream().forEach((String s)->{
//            System.out.println("LamadaTest s->"+s);
//        });
        //简写版,lamada自己做类型推断
        Consumer<String> consumer=s->System.out.println("LamadaTest s->"+s);
        test.stream().forEach(consumer);
    }
}

   上述代码编译完成后执行javap -v查看具体的字节码指令,去除代码行号表等非关键部分后如下:

Constant pool:
    #1 = Methodref          #18.#43       // java/lang/Object."<init>":()V
    #2 = Class              #44           // java/lang/String
    #3 = String             #45           // a
    #4 = String             #46           // b
    #5 = String             #47           // c
    #6 = Methodref          #48.#49       // java/util/Arrays.asList:([Ljava/lang/Object;)Ljava/util/List;
    #7 = InvokeDynamic      #0:#55        // #0:accept:()Ljava/util/function/Consumer;
    #8 = InterfaceMethodref #56.#57       // java/util/List.stream:()Ljava/util/stream/Stream;
    #9 = InterfaceMethodref #58.#59       // java/util/stream/Stream.forEach:(Ljava/util/function/Consumer;)V
   #10 = Fieldref           #60.#61       // java/lang/System.out:Ljava/io/PrintStream;
   #11 = Class              #62           // java/lang/StringBuilder
   #12 = Methodref          #11.#43       // java/lang/StringBuilder."<init>":()V
   #13 = String             #63           // LamadaTest s->
   #14 = Methodref          #11.#64       // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #15 = Methodref          #11.#65       // java/lang/StringBuilder.toString:()Ljava/lang/String;
   #16 = Methodref          #66.#67       // java/io/PrintStream.println:(Ljava/lang/String;)V
   #17 = Class              #68           // jni/LamadaTest
   #18 = Class              #69           // java/lang/Object
   #19 = Utf8               <init>
   #20 = Utf8               ()V
   #21 = Utf8               Code
   #22 = Utf8               LineNumberTable
   #23 = Utf8               LocalVariableTable
   #24 = Utf8               this
   #25 = Utf8               Ljni/LamadaTest;
   #26 = Utf8               main
   #27 = Utf8               ([Ljava/lang/String;)V
   #28 = Utf8               args
   #29 = Utf8               [Ljava/lang/String;
   #30 = Utf8               test
   #31 = Utf8               Ljava/util/List;
   #32 = Utf8               consumer
   #33 = Utf8               Ljava/util/function/Consumer;
   #34 = Utf8               LocalVariableTypeTable
   #35 = Utf8               Ljava/util/List<Ljava/lang/String;>;
   #36 = Utf8               Ljava/util/function/Consumer<Ljava/lang/String;>;
   #37 = Utf8               lambda$main$0
   #38 = Utf8               (Ljava/lang/String;)V
   #39 = Utf8               s
   #40 = Utf8               Ljava/lang/String;
   #41 = Utf8               SourceFile
   #42 = Utf8               LamadaTest.java
   #43 = NameAndType        #19:#20       // "<init>":()V
   #44 = Utf8               java/lang/String
   #45 = Utf8               a
   #46 = Utf8               b
   #47 = Utf8               c
   #48 = Class              #70           // java/util/Arrays
   #49 = NameAndType        #71:#72       // asList:([Ljava/lang/Object;)Ljava/util/List;
   #50 = Utf8               BootstrapMethods
   #51 = MethodHandle       #6:#73        // 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;
   #52 = MethodType         #74           //  (Ljava/lang/Object;)V
   #53 = MethodHandle       #6:#75        // invokestatic jni/LamadaTest.lambda$main$0:(Ljava/lang/String;)V
   #54 = MethodType         #38           //  (Ljava/lang/String;)V
   #55 = NameAndType        #76:#77       // accept:()Ljava/util/function/Consumer;
   #56 = Class              #78           // java/util/List
   #57 = NameAndType        #79:#80       // stream:()Ljava/util/stream/Stream;
   #58 = Class              #81           // java/util/stream/Stream
   #59 = NameAndType        #82:#83       // forEach:(Ljava/util/function/Consumer;)V
   #60 = Class              #84           // java/lang/System
   #61 = NameAndType        #85:#86       // out:Ljava/io/PrintStream;
   #62 = Utf8               java/lang/StringBuilder
   #63 = Utf8               LamadaTest s->
   #64 = NameAndType        #87:#88       // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   #65 = NameAndType        #89:#90       // toString:()Ljava/lang/String;
   #66 = Class              #91           // java/io/PrintStream
   #67 = NameAndType        #92:#38       // println:(Ljava/lang/String;)V
   #68 = Utf8               jni/LamadaTest
   #69 = Utf8               java/lang/Object
   #70 = Utf8               java/util/Arrays
   #71 = Utf8               asList
   #72 = Utf8               ([Ljava/lang/Object;)Ljava/util/List;
   #73 = Methodref          #93.#94       // 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;
   #74 = Utf8               (Ljava/lang/Object;)V
   #75 = Methodref          #17.#95       // jni/LamadaTest.lambda$main$0:(Ljava/lang/String;)V
   #76 = Utf8               accept
   #77 = Utf8               ()Ljava/util/function/Consumer;
   #78 = Utf8               java/util/List
   #79 = Utf8               stream
   #80 = Utf8               ()Ljava/util/stream/Stream;
   #81 = Utf8               java/util/stream/Stream
   #82 = Utf8               forEach
   #83 = Utf8               (Ljava/util/function/Consumer;)V
   #84 = Utf8               java/lang/System
   #85 = Utf8               out
   #86 = Utf8               Ljava/io/PrintStream;
   #87 = Utf8               append
   #88 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
   #89 = Utf8               toString
   #90 = Utf8               ()Ljava/lang/String;
   #91 = Utf8               java/io/PrintStream
   #92 = Utf8               println
   #93 = Class              #96           // java/lang/invoke/LambdaMetafactory
   #94 = NameAndType        #97:#101      // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值