首页
学习
活动
专区
圈层
工具
发布
    • 综合排序
    • 最热优先
    • 最新优先
    时间不限
  • 来自专栏码农架构

    Java 虚拟机:JVM是怎么实现invokedynamic的?(上)

    为了解决这个问题,Java 7 引入了一条新的指令 invokedynamic。该指令的调用机制抽象出调用点这一个概念,并允许应用程序将调用点链接至任意符合条件的方法上。 public static void startRace(java.lang.Object) 0: aload_0 // 加载一个任意对象 1: invokedynamic race // 调用赛跑方法 (理想的调用方式) 作为 invokedynamic 的准备工作,Java 7 引入了更加底层、更加灵活的方法抽象 :方法句柄(MethodHandle)。 总结与实践 今天我介绍了 invokedynamic 底层机制的基石:方法句柄。 方法句柄是一个强类型的、能够被直接执行的引用。

    1.4K30发布于 2021-02-14
  • 来自专栏码农架构

    Java 虚拟机:JVM是怎么实现invokedynamic的?(下)

    不过,我们并没有讲解 invokedynamic,而是深入地探讨了它所依赖的方法句柄。 invokedynamic 指令 invokedynamic 是 Java 7 引入的一条新指令,用以支持动态语言的方法调用。 在运行过程中,每一条 invokedynamic 指令将捆绑一个调用点,并且会调用该调用点所链接的方法句柄。 在第一次执行 invokedynamic 指令时,Java 虚拟机会调用该指令所对应的启动方法(BootStrap Method),来生成前面提到的调用点,并且将之绑定至该 invokedynamic Lambda 表达式到函数式接口的转换是通过 invokedynamic 指令来实现的。该 invokedynamic 指令对应的启动方法将通过 ASM 生成一个适配器类。

    2.4K30发布于 2021-02-14
  • 来自专栏得物技术

    浅析JVM invokedynamic指令和Java Lambda语法|得物技术

    invokedynamic执行时,BSM先被调用并返回一个 CallSite(调用点)对象,这个对象就和 invokedynamic链接在一起。 invokedynamic指令参数invokedynamic指令参数结构如下:jvms-6.5.invokedynamic (https://docs.oracle.com/javase/specs/jvms 该参数以CONSTANT_InvokeDynamic_info结构存放在类文件的常量池结构中,invokedynamic用两个byte宽度的常量池索引号指定。 ;}对照字节码我们可知,Lambda1相关的invokedynamic指定的CONSTANT_InvokeDynamic_info序号为3,得到如下内容:期望的方法名称和描述符该invokedynamic invokedynamic指令不是业务开发者使用的。invokedynamic指令可以用来实现Lambda语法,但是它不是只能用来实现Lambda语法。

    42010编辑于 2024-08-27
  • 来自专栏一个会写诗的程序员的博客

    Java JVM 动态方法调用指令 invokedynamic 实现分析(以 Lambda 表达式实现原理为例)

    一、前言 对于 invokedynamic 指令的实现需要方法句柄作为前提知识点。可参考 Java JVM 动态方法调用之方法句柄 MethodHandle。 本文以 Lambda 表达式中运用 invokedynamic 的实现分析。 转为字节码后,关键字节码如下: { public void lambda1(); Code: stack=1, locals=2, args_size=1 0: invokedynamic 代码执行 invokedynamic 指令时,将调用常量池对应的 BootstrapMethods(引导方法) ,引导方法返回一个动态调用站点对象 CallSite,该对象绑定了要执行的方法句柄。 官方-Using the invokedynamic Instruction Java 8 的 Lambda 表达式为什么要基于 invokedynamic

    1.4K11编辑于 2022-01-27
  • 来自专栏shysh95

    同事:Lambda都不懂,还写什么Java

    除了invokedynamic,其他调用指令的分派逻辑在JVM中是固定的,但是invokedynamic的分派逻辑是由用户设定的引导方法(BSM)决定的。 BSM会返回一个CallSite对象,这个对象会和invokedynamic链接在一起,再次执行这条invokedynamic也不会创建新的CallSite对象。 方法句柄和invokedynamic invokedynamic通过引导方法(BSM)来使用方法句柄,与invokevirtual指令不同的是invokedynamic指令不需要receiver,它会使用 可以看出在我们的字节码指令中已经出现了invokedynamicinvokedynamic运行时 每一个invokedynamic指令都称为Dynamic Call Site(动态调用点),invokedynamic的执行大概需要两步。 1.

    55310发布于 2021-02-25
  • 来自专栏程序亦非猿

    Android兼容Java 8语法特性的原理分析

    可见,Lambda表达式在虚拟机层面上,是通过一种名为invokedynamic字节码指令来实现的。那么invokedynamic又是何方神圣呢? invokedynamic 指令解读 invokedynamic指令是Java 7中新增的字节码调用指令,作为Java支持动态类型语言的改进之一,跟invokevirtual、invokestatic、 结合J8Sample.class字节码,并对invokedynamic指令调用过程进行跟踪分析。总结如下: ? 依据上图invokedynamic调用步骤,我们一步一步做一个分析讲解。 ; 注意,这里InvokeDynamic不是指令,代表的是Constant_InvokeDynamic_Info结构。 通过Lambda这节,我们知道Java底层是通过invokedynamic指令来实现,由于Dalvik/ART并没有支持invokedynamic指令或者对应的替代功能。

    1.1K10发布于 2019-11-07
  • 来自专栏微信公号【Java技术江湖】

    Java8特性详解 lambda表达式(三):原理篇

    invokedynamic介绍 如果有一种函数引用、指针就好了,但JVM中并没有函数类型表示。 当JVM要第一次执行某个地方的invokedynamic指令的时候,invokedynamic必须先进行链接(linkage)。 #2, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function; 5: astore_1 这里再复习一下invokedynamic 说明前面执行完invokedynamic #2, 0后,在操作数栈中插入了一个类型为Function的对象。 既然lambda表达式又不需要什么动态分派(调动哪个方法是明确的), 为什么要用invokedynamic呢?

    93220编辑于 2021-12-13
  • 来自专栏TopCoder

    java lambda 原理分析

    Java的lambda表达式实现上也就借助于invokedynamic命令。 字节码中每一处含有invokeDynamic指令的位置都称为动态调用点,这条指令的第一个参数不再是代表方法调用符号引用的CONSTANT_Methodref_info常亮,而是变成为JDK7新加入的CONSTANT_InvokeDynamic_info 根据CONSTANT_InvokeDynamic_info常量中提供的信息,虚拟机可以找到并执行引导方法,从而获得一个CallSite对象,最终调用要执行的目标方法。 从上述mian方法的字节码可见,有一个invokeDynamic指令,他的参数为第7项常量(第二个值为0的参数HotSpot中用不到,占位符)。 invokedynamic #7, 0 // InvokeDynamic #0:accept:()Ljava/util/function/Consumer; 常量池中第7项是#7 = InvokeDynamic

    91930发布于 2019-11-06
  • 来自专栏Java帮帮-微信公众号-技术文章全总结

    通过字节码分析JDK8中Lambda表达式编译及执行机制【面试+工作】

    invokedynamic指令就链接到这个CallSite对象来实现运行时绑定,也即invokedynamic指令在调用时,会通过这个勾子找到lambda所代表的一个functional接口对象(也即 invokedynamic指令特性 可以看到第一条指令就是代表了lambda表达式的实现指令,invokedynamic指令,这个指令是JSR-292开始应用的规范,而鉴于兼容和扩展的考虑(可以参考Oracle invokedynamic 在常量池中关联一个CONSTANT_InvokeDynamic_info结构,这个结构可以明确invokedynamic指令的一个引导方法(bootstrap method) 结合CONSTANT_InvokeDynamic_info的结构信息来看一下这个常量池表项包含的信息。 CONSTANT_InvokeDynamic_info结构如下: ? 简单解释下这个CONSTANT_InvokeDynamic_info的结构: tag: 占用一个字节(u1)的tag,也即InvokeDynamic的一个标记值,其会转化成一个字节的tag值。

    2.2K11发布于 2018-09-29
  • 来自专栏Linux内核及编程语言底层相关技术研究

    Java中的Lambda是如何实现的

    #3, 0 // InvokeDynamic #0:accept:(Ljava/lang/String;)Ljava/util/function/Consumer; 在main方法的字节码中,invokedynamic是整个lambda实现的关键,不过由于该字节码在JVM中的实现逻辑非常复杂,在这里我们就不看具体代码了,只说下大致思路。 JVM在执行invokedynamic字节码时,会根据class文件中提供的各种信息,调用java.lang.invoke.LambdaMetafactory.metafactory方法来动态生成这个类 在该类生成完毕之后,invokedynamic字节码会调用其getLambda方法来创建一个TestLambda1实例,该实例创建成功,也意味着invokedynamic字节码执行完毕。 当TestLambda当Test类生成完毕后,invokedynamic字节码会调用其get$Lambda方法,生成一个TestLambda 该实例创建完毕也意味着invokedynamic字节码执行完毕

    1.4K30编辑于 2023-03-15
  • 来自专栏ImportSource

    JDK11中增加了一个常量池类型:CONSTANT_Dynamic

    有关invokedynamic 我们知道在java7的时候加入了动态语言的支持。上面也说到了,虚拟机规范也添加了支持动态语言的三个常量类型: ? 这里还是简单的介绍一下invokedynamic吧。 invokedynamic是一个字节码指令,也就是bytecode instruction,通过动态方法的调用来实现动态语言。 argument list for an invokedynamic bootstrap is a sequence of constants. 有了invokedynamic以后,由于invokedynamic bootstrap的静态参数列表是一系列常量,也就是好多个常量。在常量池中存储复杂数据的情况就变得比较普遍。 所以就需要一个更丰富、更高级的常量类型,这样可以解决很多开发invokedynamic协议的麻烦,从而还能改善程序性能和简化编译器逻辑。 为此新增了CONSTANT_Dynamic常量类型。

    1.9K10发布于 2018-07-25
  • 来自专栏明明如月的技术专栏

    深入理解 Lambda 表达式

    8 aload_1 9 invokeinterface #10 <java/util/List.stream : ()Ljava/util/stream/Stream;> count 1 14 invokedynamic * Typically used as a bootstrap method for {@code invokedynamic} * call sites, to support * When used with {@code invokedynamic}, this is stacked * automatically When * used with {@code invokedynamic}, this is provided by * the {@code NameAndType} of the {@code InvokeDynamic} * structure and is stacked

    53440发布于 2021-11-29
  • 来自专栏明明如月的技术专栏

    深入理解 Lambda 表达式

    如 50 invokedynamic #10 <test, BootstrapMethods #0> 我们可以直接在插件上,点击命令跳转到对应官方说明文档中: https://docs.oracle.com * Typically used as a bootstrap method for {@code invokedynamic} * call sites, to support * When used with {@code invokedynamic}, this is stacked * automatically When * used with {@code invokedynamic}, this is provided by * the {@code NameAndType} of the {@code InvokeDynamic} * structure and is stacked

    55010编辑于 2022-02-15
  • 来自专栏猫头虎博客专区

    Java字节码深度知多少?

    4、invokedynamic 有时候在写一些python脚本或者js脚本的时候,会特别羡慕这些动态语言。如果把查找目标方法的决定权,从虚拟机转嫁给用户代码,我们就会有更高的自由度。 我们单独把invokedynamic抽离出来介绍,是因为它比较复杂。和反射类似,它用于一些动态的调用场景,但它和反射有着本质的不同,效率也比反射要高的多。 和上面介绍的四个指令不同,invokedynamic并没有确切的接收对象,取而代之的,是一个叫做 CallSite 的对象。 除了lambda表达式,我们还没有其他的方式来产生invokedynamic指令。 我们了解到Java7之后的invokedynamic指令,它实际上是通过方法句柄来实现的。

    32510编辑于 2024-04-08
  • 来自专栏疯狂软件李刚

    Java与Scala如何编译Lambda表达式?

    它并没有创建包装Lambda函数的新对象,而是使用Java 7新引进的invokeDynamic指令将此调用点动态链接到实际的Lambda函数。 invokedynamic #0:apply:()Ljava/util/function/Function; // 调用它的map()函数 invokeinterface java/util/stream /Stream.map: (Ljava/util/function/Function;)Ljava/util/stream/Stream; InvokeDynamic魔术:在Java 7中添加了此JVM 动态链接:如果查看实际的invokedynamic指令,你将看到没有实际Lambda函数的引用(称为lambda$0)。 答案在于invokedynamic的设计方式(该指令的设计非常优雅,下次我们专门写一篇文章来介绍该指令),简单来说,就在于Lambda的名称和签名,在我们的例子中有如下代码: // lambda$0函数获取一个

    1.8K10发布于 2020-06-24
  • 来自专栏猫头虎博客专区

    Lambda表达式性能优化:JDK 17和JDK 21中Lambda如何提升性能与可读性?

    JDK 8中的Lambda实现:invokedynamic机制 在JDK 8中,Lambda表达式的实现基于invokedynamic指令: 编译时,Lambda表达式会生成调用invokedynamic Thread.sleep(100); // 确保线程执行完成 } } Lambda性能优化流程图 以下是Lambda在JDK 8、JDK 17和JDK 21的性能优化流程: 说明: JDK 8使用invokedynamic 总结:Lambda性能优化的关键点 版本 优化内容 优势 JDK 8 基于invokedynamic动态生成匿名类 灵活,但开销较大,元空间消耗较高。

    56910编辑于 2024-12-18
  • 来自专栏实战docker

    Java虚拟机学习:方法调用的字节码指令

    invokedynamic:调用动态方法; 这里我们通过一个实例将这些方法调用的字节码指令逐个列出。 bolingcavalry/Action.doAction:()V 33: return public void createThread(); Code: 0: invokedynamic #13, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable; 5: astore_1 6: return // InvokeDynamic #0:run:()Ljava/lang/Runnable; 5: astore_1 6: return 可见lambda表达式对应的实际上是一个 invokedynamic调用,具体的调用内容,可以用Bytecode viewer这个工具来打开Test001.class再研究,由于反编译后得到invokedynamic的操作数是#13,我们先去常量池看看

    925100发布于 2018-01-04
  • 深入探索Java类加载与字节码技术:从字节码指令集到Lambda表达式实现

    invokedynamic与Lambda表达式实现 在Java字节码指令集中,invokedynamic是一个革命性的存在。 invokedynamic的核心机制 invokedynamic指令的工作流程可以分为三个关键阶段:引导方法调用、调用点绑定和动态链接。 Lambda表达式的实现奥秘 Java 8引入的Lambda表达式正是基于invokedynamic实现的。 invokedynamic指令在Lambda表达式实现中的应用 动态调用点的实现细节 调用点(CallSite)是invokedynamic架构中的关键抽象,主要分为三种类型: • ConstantCallSite 动态语言支持的技术深化 invokedynamic指令的出现为JVM打开了动态语言支持的大门,但其潜力远未被充分挖掘。

    34611编辑于 2025-08-27
  • 来自专栏JAVA高级架构开发

    Java虚拟机学习:方法调用的字节码指令

    invokespecial:调用私有实例方法; 2. invokestatic:调用静态方法; 3. invokevirtual:调用实例方法; 4. invokeinterface:调用接口方法; 5. invokedynamic invokeinterface指令来实现的; 其实t.doAction()和a.doAction()最终都是调用Test001的实例的doAction,但是t的声明是类,a的声明是接口,所以两者的调用指令是不同的; invokedynamic :调用动态方法 在main()方法中,我们声明了一个lambda() -> System.out.println(“123”),反编译的结果如下: 0: invokedynamic #13, 0 5 : astore_1 6: return 1 可见lambda表达式对应的实际上是一个invokedynamic调用,具体的调用内容,可以用Bytecode viewer这个工具来打开Test001. class再研究,由于反编译后得到invokedynamic的操作数是#13,我们先去常量池看看13对应的内容: 是个Name and type和Bootstrap method,再细看Bootstrap

    1.3K00发布于 2018-09-28
  • 来自专栏JAVA高级架构开发

    Java虚拟机学习:方法调用的字节码指令

    invokedynamic:调用动态方法; 这里我们通过一个实例将这些方法调用的字节码指令逐个列出。 28: invokeinterface #12,  1                 33: returnpublic void createThread();    Code:       0: invokedynamic :调用动态方法 在main()方法中,我们声明了一个lambda() -> System.out.println(“123”),反编译的结果如下: 0: invokedynamic #13,  0                    5: astore_1       6: return 1 可见lambda表达式对应的实际上是一个invokedynamic调用,具体的调用内容,可以用Bytecode viewer这个工具来打开 Test001.class再研究,由于反编译后得到invokedynamic的操作数是#13,我们先去常量池看看13对应的内容: 是个Name and type和Bootstrap method,再细看

    67300发布于 2018-09-28
领券