• 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应用解析

  • 相关阅读:
    Kubernetes 1.5 配置dns
    详细图解,一眼就能看懂!卷帘快门(Rolling Shutter)与全局快门(Global Shutter)的区别
    把C#程序(含多个Dll)合并成一个Exe的超简单方法
    TortoiseSVN 合并操作简明教程
    简单说说.Net中的弱引用
    漫谈并发
    可靠UDP设计
    自动内存管理算法 —— 标记和复制法
    Unity防破解 —— 加密Dll与Key保护
    Unity防破解 —— 重新编译mono
  • 原文地址:https://www.cnblogs.com/strongmore/p/15467757.html
Copyright © 2020-2023  润新知