在 Java 中,JVM 可以理解的代码就叫做(即扩展名为 .class 的⽂件),它不⾯向任何特定的处理器,只⾯向虚拟机。Java 语⾔通过字节码的⽅式,在⼀定程度上解决了传统解释型语⾔执⾏效率低的问题,同时⼜保留了解释型语⾔可移植的特点。所以 Java 程序运⾏时⽐᫾⾼效,⽽且,由于字节码并不针对⼀种特定的机器,因此,Java 程序⽆须重新编译便可在多种不同操作系统的计算机上运⾏。

Java 程序从源代码到运⾏⼀般有下⾯ 3 步:

我们需要格外注意的是 .class->机器码 这⼀步。在这⼀步 JVM 类加载器⾸先加载字节码⽂件, 然后通过解释器逐⾏解释执⾏,这种⽅式的执⾏速度会相对⽐较慢。⽽且,有些⽅法和代码块是经常需要被调⽤的(也就是所谓的热点代码),所以后⾯引进了 JIT 编译器,⽽ JIT 属于运⾏时编译。当 JIT 编译器完成第⼀次编译后,其会将字节码对应的机器码保存下来,下次可以直接使⽤。⽽我们知道,机器码的运⾏效率肯定是⾼于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语⾔。

HotSpot 采⽤了惰性评估(Lazy Evaluation)的做法,根据⼆⼋定律,消耗⼤部分系统资源的只有那⼀⼩部分的代码(热点代码),⽽这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执⾏的情况收集信息并相应地做出⼀些优化,因此执⾏的次数越多,它的速度就越快。JDK 9 引⼊了⼀种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了 JIT 预热等各⽅⾯的开销。JDK ⽀持分层编译和 AOT 协作使⽤。但是 ,AOT 编译器的编译质量是肯定⽐不上 JIT 编译器的。