JAVA 是一种跨平台的编程语言 。程序源代码会被编译为 字节码bytecode , 然后字节码在运行时被转换为 机器码machine code 。解释器interpreter 在物理机器上模拟出的抽象计算机上执行字节码指令 。即时just-in-time(JIT)编译发生在运行期,而 预先ahead-of-time(AOT)编译发生在构建期 。
本文将说明解释器、JIT 和 AOT 分别何时起作用,以及如何在 JIT 和 AOT 之间权衡 。
源代码、字节码、机器码应用程序通常是由 C、C++ 或 Java 等编程语言编写 。用这些高级编程语言编写的指令集合称为源代码 。源代码是人类可读的 。要在目标机器上执行它 , 需要将源代码转换为机器可读的机器码 。这个转换工作通常是由 编译器compiler
然而,在 Java 中 , 源代码首先被转换为一种中间形式 , 称为字节码 。字节码是平台无关的,所以 Java 被称为平台无关编程语言 。Java 编译器 javac
将源代码转换为字节码 。然后解释器解释执行字节码 。
下面是一个简单的 Java 程序, Hello.java
:
//Hello.javapublic class Hello {public static void mAIn(String[] args) {System.out.println("Inside Hello World!");}}
使用 javac
编译它,生成包含字节码的 Hello.class
文件 。
$ javac Hello.java$ lsHello.classHello.java
现在,使用 javap
来反汇编 Hello.class
文件的内容 。使用 javap
时如果不指定任何选项,它将打印基本信息,包括编译这个 .class
文件的源文件、包名称、公共和受保护字段以及类的方法 。
$ javap Hello.classCompiled from "Hello.java"public class Hello {public Hello();public static void main(java.lang.String[]);}
要查看 .class
文件中的字节码内容 , 使用 -c
选项:
$ javap -c Hello.classCompiled from "Hello.java"public class Hello {public Hello();Code:0: aload_01: invokespecial #1// Method java/lang/Object."<init>":()V4: returnpublic static void main(java.lang.String[]);Code:0: getstatic#2// Field java/lang/System.out:Ljava/io/PrintStream;3: ldc#3// String Inside Hello World!5: invokevirtual #4// Methodjava/io/PrintStream.println:(Ljava/lang/String;)V8: return}
要获取更详细的信息,使用 -v
选项:
$ javap -v Hello.class
解释器 , JIT 和 AOT解释器负责在物理机器上模拟出的抽象计算机上执行字节码指令 。当使用 javac
编译源代码,然后使用 java
执行时,解释器在程序运行时运行并完成它的目标 。
$ javac Hello.java$ java HelloInside Hello World!
JIT 编译器也在运行期发挥作用 。当解释器解释 Java 程序时,另一个称为运行时 分析器profiler 的组件将静默地监视程序的执行,统计各部分代码被解释的次数 。基于这些统计信息可以检测出程序的 热点hotspot,即那些经常被解释的代码 。一旦代码被解释次数超过设定的阈值 , 它们满足被 JIT 编译器直接转换为机器码的条件 。所以 JIT 编译器也被称为分析优化的编译器 。从字节码到机器码的转换是在程序运行过程中进行的,因此称为即时编译 。JIT 减少了解释器将同一组指令模拟为机器码的负担 。
AOT 编译器在构建期编译代码 。在构建时将需要频繁解释和 JIT 编译的代码直接编译为机器码可以缩短 Java 虚拟机Java Virtual Machine(JVM) 的预热warm-up时间 。(LCTT 译注:Java 程序启动后首先字节码被解释执行,此时执行效率较低 。等到程序运行了足够的时间后,代码热点被检测出来 , JIT 开始发挥作用 , 程序运行效率提升 。JIT 发挥作用之前的过程就是预热 。)AOT 是在 Java 9 中引入的一个实验性特性 。jaotc
使用 Graal 编译器(它本身也是用 Java 编写的)来实现 AOT 编译 。
以 Hello.java
为例:
//Hello.javapublic class Hello {public static void main(String[] args) {System.out.println("Inside Hello World!");}}$ javac Hello.java$ jaotc --output libHello.so Hello.class$ java -XX:+UnlockExperimentalVMOptions -XX:AOTLibrary=./libHello.so HelloInside Hello World!
解释和编译发生的时机下面通过例子来展示 Java 在什么时候使用解释器,以及 JIT 和 AOT 何时参与进来 。这里有一个简单的程序 Demo.java
:
//Demo.javapublic class Demo {public int square(int i) throws Exception {return(i*i);}public static void main(String[] args) throws Exception {for (int i = 1; i <= 10; i++) {System.out.println("call " + Integer.valueOf(i));long a = System.nanoTime();Int r = new Demo().square(i);System.out.println("Square(i) = " + r);long b = System.nanoTime();System.out.println("elapsed= " + (b-a));System.out.println("--------------------------------");}}}
推荐阅读
- 应采儿晒和大儿子逛吃vlog,Jasper自编自导自演,母子互动有趣
- 温和不刺激的护肤品有哪些 十大保湿温和护肤品品牌排行榜
- spss信度分析步骤,spss信度和效度分析怎么做
- 游本昌演济公时,遇3件怪事,至今无法用科学解释,拍完立刻出家
- 华为play4t和play4tpro有什么区别
- 虾和哪些蔬菜最佳搭配 大虾和哪些蔬菜一块炒
- 饭店名字大全和寓意吉字开头 饭店名字大全和寓意
- 孙姓发源地
- 豆浆和鸡蛋一起吃会消化不良?
- 客厅招财风水有哪些注意事项和禁忌 客厅招财风水有哪些注意事项