Java-JIT

JIT

JIT:Just In Time Compiler,翻译为即使编译器,这是针对解释型语言而言的,而且并非虚拟机必须,是一种优化手段。Hotspot就有这种技术,Java虚拟机标准对JIT的存在没有作出任何规范,所以这是虚拟机实现的自定义优化技术。

HotSpot虚拟机的执行引擎在执行Java代码是可以采用解释执行编译执行两种方式的。如果采用的是编译执行方式,那么就会使用到JIT,而解释执行就不会使用到JIT。所以,早期说Java是解释型语言,是没有任何问题的,而在拥有JIT的Java虚拟机环境下,说Java是解释型语言严格意义上已经不正确了。

HotSpot中的编译器是javac,它的工作就是将java代码编译为可执行的class文件,这部分工作是完全独立的,完全不需要运行时参与,所以java程序的编译是半独立实现的。有了字节码,就由解释器来进行解释执行,这是早期java虚拟机的工作流程。

后来,java虚拟机会将执行频率高的方法或者语句块通过JIT编译成本地机器码,提高了代码执行的效率。

工作原理

当JIT编译启用时(默认是启用的),JVM读入.class文件解释后,将其发给JIT编译器。JIT编译器将字节码编译成本机机器代码。

通常javac将程序源码编译,转换成java字节码,JVM通过解释字节码将其翻译成相应的机器指令,逐条读入,逐条解释翻译。非常显然,经过解释运行,其运行速度必定会比可运行的二进制字节码程序慢。为了提高运行速度,引入了JIT技术。

在执行时JIT会把翻译过的机器码保存起来,已备下次使用,因此从理论上来说,采用该JIT技术能够接近纯编译技术。

JIT

但是JIT并不总能奏效,不能期望JIT一定可以加速你代码运行的速度,它有可能减少代码的运行速度。这取决于你的代码结构,当然非常多情况下我们还是可以如愿以偿的。

分析.class到机器码

JVM 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。

我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。

HotSpot 采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。

JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各方面的开销。JDK 支持分层编译和 AOT 协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。

你可能感兴趣的:(Java-JIT)