Scala 为 JVM 1.7 生成字节码的优势

Posted

技术标签:

【中文标题】Scala 为 JVM 1.7 生成字节码的优势【英文标题】:Advantages of Scala emitting bytecode for the JVM 1.7 【发布时间】:2012-12-26 11:47:47 【问题描述】:

根据 Scala 2.10,与默认为 1.6 发出字节码相比,为 JVM 1.7 发出字节码有哪些优势(如果有)?

【问题讨论】:

JVM 1.7 带来了InvokeDynamic,我确信它可以在 Scala 的几个地方使用(结构类型、特征 Dynamic 等等),但我不知道是否编译器利用它 ***.com/questions/13380807/…中的一些细节 @dicarlo2:我不认为 trait Dynanic 使用 invokedynamic。它是 applyDynamic 方法调用的糖。但是对结构类型的方法调用是调用动态的候选对象。 @v6ak 啊,你说得对,我误解了Dynamic 的工作原理。 您是否只对 scala 2.10 目前实现的实际优势感兴趣,或者还在寻找 scala 如何假设从 JVM 1.7 的新功能中受益? 【参考方案1】:

以前的 Scala 版本发出 49.0 版的字节码,对应于 Java 5。使用 Scala 2.10 版the default was changed to version 50.0,对应于 Java 6,其主要优点是激活该版本引入的更快的验证器,因此它应该会导致(稍微)更好的运行时性能。

正如您所注意到的,在 2.10 中,可以发出 51.0 版本的字节码,它对应于 Java 7。50.0 版本和 51.0 版本之间存在一些差异:最大的是包含了 invokedynamic 指令,其中与之配套的管道(有关血腥细节,请参阅the class file format definition)。

就 Scala 对 51.0 字节代码的使用而言,尽管技术部分已经到位,但我的理解是,使用此功能的工作仍处于实验阶段。请参阅 this EPFL presentation 和 this thread,这表明团队正在努力获得方法句柄的性能优势,而不必引入对 Java 7 的依赖。

Scala 2.11 保留了发出版本 50.0 字节码的默认设置,但 official plan 现在使用 Scala 2.12 直接跳转到 Java 8 字节码。同时,有一个可用于 Scala 2.11 的new back-end,可让您试用为 Scala 2.12 设计的some of the features,它将成为 Scala 2.12 的默认后端。

无论如何,期待已久的提议好处都来自使用invokedynamic 字节码(及其相关的 MethodHandle 结构)。它们包括:

reducing code size and execution time for closures improving specialization of generic datatypes potentially faster structural types

(剧透:使用MethodHandles 在实验后端实现闭包目前比目前优化的闭包创建慢!)

【讨论】:

很好的答案!但是关于验证者提高的性能,它会影响执行还是仅仅影响初始化? Java 6 验证器优化了类加载,例如this question and answers。 @Hugo,它所做的只是加速类加载。基本上,JVM 必须检查字节码中所有内容的类型以确保其有效。经典验证程序运行完整的数据流分析,以解释条件和循环等内容。但是现代类文件包含断言所有类型的元数据,因此验证者可以验证它是否匹配一次。

以上是关于Scala 为 JVM 1.7 生成字节码的优势的主要内容,如果未能解决你的问题,请参考以下文章

JVM技术专题针对于Class字节码的文件分析和研究指南 「 入门篇」

jvm 字节码学习

Scala 特征是如何编译成 Java 字节码的?

scala的反射

JVM技术专题针对于Class字节码的文件分析和研究指南 「 进阶篇」

JVM 字节码的结构