zoukankan      html  css  js  c++  java
  • java中Lambda表达式的实现原理

    简单使用

    import java.util.function.Consumer;
    
    public class TestLambda {
    
      public static void main(String[] args) {
        Consumer<String> consumer = System.out::println;
        consumer.accept("hello");
      }
    
    }
    

    反编译后字节码

    getstatic #2 <java/lang/System.out>
    dup
    invokestatic #3 <java/util/Objects.requireNonNull>
    pop
    invokedynamic #4 <accept, BootstrapMethods #0>
    astore_1
    aload_1
    ldc #5 <hello>
    invokeinterface #6 <java/util/function/Consumer.accept> count 2
    return
    

    invokedynamic是Java 7为了实现在JVM上运行动态语言而引入的一条新的虚拟机指令,它可以实现在运行期动态解析出调用点限定符所引用的方法,
    然后再执行该方法,invokedynamic指令的分派逻辑是由用户设定的引导方法决定。Lambda表达式的核心就是invokedynamic指令。

    实现原理

    通过debug可知,Lambda表达式最终是通过InnerClassLambdaMetafactory类来创建匿名内部类来实现的,使用ASM来创建匿名内部类

    最后通过Unsafe(java提供的魔法类,可以操作底层资源)的defineAnonymousClass()方法来将字节数组转换成Class对象,
    类似于ClassLoader的loadClass()方法的功能,但这种方法生成的匿名类不显式挂在任何ClassLoader下面,只要当该类没有存在的实例对象、
    且没有强引用来引用该类的Class对象时,该类就会被GC回收。因此这种匿名内部类相比于Java语言层面的匿名内部类更容易回收。

    通过匿名内部类的Class对象创建调用点CallSite

    总结

    在Lambda表达式实现中,通过invokedynamic指令调用引导方法生成调用点,在此过程中,会通过ASM动态生成字节码,
    而后利用Unsafe的defineAnonymousClass方法定义实现相应的函数式接口的匿名类,然后再实例化此匿名类,
    并返回与此匿名类中函数式方法的方法句柄关联的调用点;而后可以通过此调用点实现调用相应Lambda表达式定义逻辑的功能。

    参考

    Java魔法类:Unsafe应用解析

  • 相关阅读:
    Mybatis批处理
    Mybatis兼容C3P0连接池
    一对多,多对一查询
    缓存
    动态sql
    mybatis 日志记录
    python学习day07-encode和decode
    python学习day07---三级目录优化
    python学习day06练习---三级目录
    python学习day06--02字典增删差改以及字符串的一些方法
  • 原文地址:https://www.cnblogs.com/strongmore/p/15467757.html
Copyright © 2011-2022 走看看