09 | JVM是怎么实现invokedynamic的?(下)
该思维导图由 AI 生成,仅供参考
invokedynamic 指令
- 深入了解
- 翻译
- 解释
- 总结
Java 7中引入了invokedynamic机制,允许动态语言的方法调用。invokedynamic指令将调用点抽象成一个Java类,并将方法调用和链接暴露给应用程序。在Java 8中,Lambda表达式也是借助invokedynamic来实现的。通过深入分析invokedynamic和Lambda表达式的实现原理,为读者提供了对Java虚拟机内部机制的深入理解和性能优化的启示。Lambda表达式的性能分析显示,即时编译器能够将invokedynamic和对目标方法的调用统统内联进来,最终优化为空操作。然而,带捕获变量的Lambda表达式可能会导致额外的新建实例开销,需要注意逃逸分析的影响。文章还介绍了不同版本的代码实践,展示了方法句柄的性能特点。通过这些内容,读者可以快速了解invokedynamic和Lambda表达式的实现原理,以及在实际编程中的性能优化技巧。
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
全部留言(32)
- 最新
- 精选
- Shine一直没理解“逃逸分析”啥意思?
作者回复: 逃逸分析是指通过数据流分析,判断一个对象会不会被传递到当前编译的方法之外。比如说你调用了一个方法,将一个新建的对象作为参数传递出去,如果这个方法没有被内联,则说明该新建对象会逃逸。 逃逸分析是一项比较重要的优化,我后面会详细讲。
2018-08-1427 - 素丶https://zhuanlan.zhihu.com/p/26389041 https://zhuanlan.zhihu.com/p/30936412 可以和 Shijie 大大的两篇文章配合着看。
作者回复: 赞!
2018-11-07321 - karl看了两遍 勉强有个概念了 还是基础不够 看不懂啊
作者回复: invokedynamic涉及到的东西很多,底层实现也在不断改进。看懂个大概就好啦
2018-08-1419 - ext4我知道Java对Lambda有个规定:“The variable used in Lambda should be final or effectively final",也就是说Lambda表达式捕获的变量必须是final或等同于final的。而文中您又讲到:“对于捕获了变量的Lambda,每次invokedynamic都需要新建适配器类实例,以防止他们发生变化”。JVM之所以这么做,是因为这种final的要求仅限于Java source层面,在bytecode层面是是无法保证的。我理解的对吗?
作者回复: 语言里的final,是对于当前方法调用而言的。这是因为它实际上就传了个值进去。比如说你定义了int a,然后传入 i -> i +a里,那么之后你对a的修改lambda是看不到的。 适配器针对的是多次不同调用,比如说每次调用你定义的final int a都不一样。
2018-08-1117 - Scott老师你好,我有两个问题,1是我看了几个有invokedynmaic指令的文件,都是invokedynamic #31, 0这种形式,似乎后面这个0没有什么作用,网上invokedynamic的解说也大多过时,我使用的是1.8.0_181版本。2. v10版本和v11版本性能的差距我猜想是v10版本不能正确的内联方法吧?虽然mh是final的,但是字节码层面已经丢失这个信息了。
作者回复: 1. 这个数字0,指的是第几个bootstrap method,你多定义几个lambda,应该可以见到1 2 3等等。 2. 对的,是不能内联。不过,字节码中字段处还是会有final标志的。C2认为final实例字段在编译过程中不应该被认为是不变的,因为应用程序可能通过Unsafe来更改。Graal认为可以当成不变的,毕竟Java语言规范没有规定不可以。 V11的话,可以看出ConstantCallsite及时子类被特殊对待了。
2018-08-194 - 小橙橙其实有个地方一直没有想透,为什么要学习字节码,学习字节码对我们日常开发有什么作用吗,老师能否给指点迷津一下?
作者回复: 主要是了解底层实现。 对普通的日常开发可能作用不大。对于进阶的,比如分析应用的性能瓶颈,了解字节码将有所帮助。
2018-08-192 - Void_seT单态内联缓存的实现代码段,bootstrap方法的实现有问题,没有return一个CallSite类型返回值。另外,这篇有点难度了,看了三遍,勉强理解。
作者回复: 多谢指出!
2018-08-11 - lantern用invokedynamic实现lambda发生了什么是看懂了,但没有完全想明白这么做的必要性,这样做相比于编译时解lambda语法糖生成一个匿名类有什么好处呢 是因为对于不捕获局部变量的lambda不用反复new对象吗,那么对于需要捕获局部变量的情况invokedynamic的实现方式还有什么其他的好处吗2020-08-1614
- Kfreer如果该 Lambda 表达式捕获了其他变量,那么每次执行该 invokedynamic 指令,我们都要更新这些捕获了的变化。 问题:捕获的变量必须是final,为什么还会变呢,为什么会线程不安全呢?2019-02-1714
- 小鳄鱼老师,看来上一篇和这篇,又两个问题: 1. 尽管逃逸分析能够去除这些额外的新建实例开销,但是它也不是时时奏效。那么什么情况下不奏效呢? 2. 什么情况下编译器会将句柄识别成常量?除了本文中将MethodHandler定义为常量外,在其他什么情况下能识别为常量呢2018-11-1523