最近我参加了一个关于 Java 效率的讨论。在我听的时候,很多反对 Java 的论点是解释是“非常耗时”的,因此即使是简单的 Java 程序也比直接编译成机器代码的类似程序运行起来要慢得多。
对此的回答是,Java 代码通常直接编译为机器代码,如果只有 JVM 计算它会使程序比以标准方式解释它更快。
我的问题是:JVM 什么时候真正“决定”执行即时编译?使 JIT 比标准字节码解释更有效的标准是什么?我的意思是,编译本身需要一些时间,据我所知,这一切都应该在程序已经运行时发生?
最近我参加了一个关于 Java 效率的讨论。在我听的时候,很多反对 Java 的论点是解释是“非常耗时”的,因此即使是简单的 Java 程序也比直接编译成机器代码的类似程序运行起来要慢得多。
对此的回答是,Java 代码通常直接编译为机器代码,如果只有 JVM 计算它会使程序比以标准方式解释它更快。
我的问题是:JVM 什么时候真正“决定”执行即时编译?使 JIT 比标准字节码解释更有效的标准是什么?我的意思是,编译本身需要一些时间,据我所知,这一切都应该在程序已经运行时发生?
这取决于您的 JVM 及其设置。维基百科:
例如,Sun 的 Java 虚拟机有两种主要模式——客户端和服务器。在客户端模式下,执行最少的编译和优化,以减少启动时间。在服务器模式下,会执行大量编译和优化,以通过牺牲启动时间来最大化应用程序运行后的性能。其他 Java 即时编译器使用运行时测量方法执行的次数以及方法的字节码大小作为决定何时编译的启发式方法。 [4] 还有一个使用执行次数与循环检测相结合。 [5]
在服务器模式下的普通 HotSpot JVM 的粗略近似是,当 JVM 注意到某个方法已被多次调用时发生 JIT,通常超过某个特定次数。(这就是 JVM 被称为“HotSpot”的原因——因为它可以识别和优化代码中的“热点”。)此时,JVM 知道一些事情:
if
语句的一个分支比另一个更常见,那么它可以改进 分支预测List
传递给此方法的 a 通常是 a ArrayList
,那么它可以针对 a 的特定情况进行优化和内联ArrayList
。请注意,如果您提前编译为机器代码,则不会有很多此类信息可供优化 - 编译器事先不知道哪些路径往往比其他路径更常见。但是,如果您等到拥有真实数据后再进行优化,您可以做出更好的优化决策。
更多关于 JIT 所做的事情的细节在这里。