网站开发遇到的风险,怎样免费安装wordpress,类似Wordpress知乎,邢台移动网站设计[1] JVM解释器 JVM设计的初衷仅仅只是为了满足Java程序实现跨平台特性#xff0c;因此避免采用静态编译的方式直接生成本地机器指令#xff0c;从而诞生了实现解释器在运行时采用逐行解释字节码的执行程序。 解释器真正意义上所承担的角色就是一个运行时“翻译者”#xff0… [1] JVM解释器 JVM设计的初衷仅仅只是为了满足Java程序实现跨平台特性因此避免采用静态编译的方式直接生成本地机器指令从而诞生了实现解释器在运行时采用逐行解释字节码的执行程序。 解释器真正意义上所承担的角色就是一个运行时“翻译者”将字节码文件中的内容“翻译”为对应平台的本地机器指令执行当一条字节码指令被解释执行完成后接着再根据PC寄存器中记录的下一条需要被执行的字节码指令执行解释操作。 由于解释器在设计和实现上非常简单因此除了Java语言之外还有许多高级语言同样也是基于解释器执行的比如Python、 Perl、Ruby等。 但是在今天基于解释器执行已经沦落为低效的代名词但无论如何基于解释器的执行模式仍然为中间语言的发展做出了不可磨灭的贡献。 [2] JIT编译器 Java中三个编译器 Java 语言的“编译器” 其实是一段“不确定”的操作过程因为它可能是指一个前端编译器其实叫“编译器的前端” 更准确一些把.java文件转变成.class文件的过程。 也可能是指虚拟机的后端运行期编译器JIT 编译器Just In Time Compiler把字节码转变成机器码的过程。 还可能是指使用静态提前编译器AOT 编译器Ahead Of Time Compiler直接把.java文件编译成本地机器代码的过程。 Java中三个编译名词 1、动态编译dynamic compilation指的是“在运行时进行编译”与之相对的是事前编译ahead-of-time compilation简称AOT也叫静态编译static compilation。 2、JIT编译just-in-time compilation狭义来说是当某段代码即将第一次被执行时进行编译因而叫“即时编译”。JIT编译是动态编译的一种特例。JIT编译一词后来被泛化时常与动态编译等价但要注意广义与狭义的JIT编译所指的区别。 3、自适应动态编译adaptive dynamic compilation也是一种动态编译但它通常执行的时机比JIT编译迟先让程序“以某种式”先运行起来收集一些信息之后再做动态编译。这样的编译可以更加优化。 JIT编译器 在部分商用虚拟机中如HotSpotJava程序最初是通过解释器Interpreter进行解释执行的当虚拟机发现某个方法或代码块的运行特别频繁时就会把这些代码认定为“热点代码”。 为了提高热点代码的执行效率在运行时虚拟机将会把这些代码编译成与本地平台相关的机器码并进行各种层次的优化完成这个任务的编译器称为即时编译器Just In Time Compiler。 即时编译器并不是虚拟机必须的部分Java虚拟机规范并没有规定Java虚拟机内必须要有即时编译器存在更没有限定或指导即时编译器应该如何去实现。 但是即时编译器编译性能的好坏、代码优化程度的高低却是衡量一款商用虚拟机优秀与否的最关键的指标之一它也是虚拟机中最核心且最能体现虚拟机技术水平的部分。 由于Java虚拟机规范并没有具体的约束规则去限制即使编译器应该如何实现所以这部分功能完全是与虚拟机具体实现相关的内容如无特殊说明我们提到的编译器、即时编译器都是指Hotspot虚拟机内的即时编译器虚拟机也是特指HotSpot虚拟机。 [3] HotSpot虚拟器中解释器和编译器如何并存 尽管并不是所有的Java虚拟机都采用解释器与编译器并存的架构但许多主流的商用虚拟机如HotSpot都同时包含解释器和编译器。 解释器与编译器两者各有优势当程序需要迅速启动和执行的时候解释器可以首先发挥作用省去编译的时间立即执行。 在程序运行后随着时间的推移编译器逐渐发挥作用把越来越多的代码编译成本地代码之后可以获取更高的执行效率。 当程序运行环境中内存资源限制较大如部分嵌入式系统中可以使用解释器执行节约内存反之可以使用编译执行来提升效率。此外如果编译后出现“罕见陷阱”可以通过逆优化退回到解释执行。 解释器的执行抽象的看是这样的输入的代码 - [ 解释器 解释执行 ] - 执行结果 而要JIT编译然后再执行的话抽象的看则是输入的代码 - [ 编译器 编译 ] - 编译后的代码 - [ 执行 ] - 执行结果 说JIT比解释快其实说的是“执行编译后的代码”比“解释器解释执行”要快并不是说“编译”这个动作比“解释”这个动作快。 JIT编译再怎么快至少也比解释执行一次略慢一些而要得到最后的执行结果还得再经过一个“执行编译后的代码”的过程。 所以对“只执行一次”的代码而言解释执行其实总是比JIT编译执行要快。怎么算是“只执行一次的代码”呢粗略说下面两个条件同时满足时就是严格的“只执行一次” 1、只被调用一次例如类的构造器class initializer() 2、没有循环 对只执行一次的代码做JIT编译再执行可以说是得不偿失。 对只执行少量次数的代码JIT编译带来的执行速度的提升也未必能抵消掉最初编译带来的开销。 只有对频繁执行的代码JIT编译才能保证有正面的收益。 对一般的Java方法而言编译后代码的大小相对于字节码的大小膨胀比达到10x是很正常的。 同上面说的时间开销一样这里的空间开销也是只有对执行频繁的代码才值得编译如果把所有代码都编译则会显著增加代码所占空间导致“代码爆炸”。 这也就解释了为什么有些JVM会选择不总是做JIT编译而是选择用解释器JIT编译器的混合执行引擎。