深入理解JVM原理4-为何JVM需要使用解释器和编译器并存的架构?

1 编译的时间开销

  • 解释器的执行,抽象的看是这样的:
    输入的代码 -> [ 解释器解释执行 ] -> 执行结果

  • 而要JIT编译然后再执行的话,抽象的看则是:
    输入的代码 -> [ 编译器编译 ] -> 编译后的代码 -> [ 执行 ] -> 执行结果

注意,需要重点说明的是,一般说JIT比解释器快,其实说的是“执行编译后的代码”比“解释器解释执行”要快,并不是说“编译”这个动作比“解释”这个动作快。

因为JIT编译动作再怎么快,至少也比解释执行一次略慢一些,而要得到最后的执行结果还得再经过一个“执行编译后的代码”的过程。所以,对“只执行一次”的代码而言,解释执行其实总是比JIT编译执行要快。

怎么才算是“只执行一次的代码”呢?
粗略说,下面两个条件同时满足时就是严格的“只执行一次”
1、只被调用一次,例如类的构造器(class initializer,())
2、没有循环
对只执行一次的代码做JIT编译再执行,可以说是得不偿失。对只执行少量次数的代码,JIT编译带来的执行速度的提升也未必能抵消掉最初编译带来的开销。只有对频繁执行的代码,JIT编译才能保证有正面的收益。

2 编译的空间开销

对一般的Java方法而言,编译后代码的大小相对于字节码的大小,膨胀比达到10x是很正常的。同上面说的时间开销一样,这里的空间开销也是,只有对执行频繁的代码才值得编译,如果把所有代码都编译则会显著增加代码所占空间,导致“代码爆炸”。

3 解释器与编译器各有优势

尽管并不是所有的Java虚拟机都采用解释器与编译器并存的架构,但许多主流的商用虚拟机(如HotSpot),都同时包含解释器编译器
解释器与编译器两者各有优势:

  • 当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。
  • 当程序运行环境中内存资源十分有限的系统中(如部分嵌入式系统中),可以使用解释器执行节约内存,反之可以使用编译执行来提升效率。

这也就解释了为什么有些JVM会选择不总是做JIT编译,而是选择用[解释器+JIT编译器]的混合执行引擎。

4 HotSpot中实现的两个不同的即时编译器

HotSpot虚拟机中内置了两个即时编译器:Client Complier和Server Complier,简称为C1、C2编译器,分别用在客户端和服务端。目前主流的HotSpot虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作。

程序使用哪个编译器,取决于虚拟机运行的模式。HotSpot虚拟机会根据自身版本与宿主机器的硬件性能自动选择运行模式,用户也可以使用“-client”或“-server”参数去强制指定虚拟机运行在Client模式或Server模式。

用Client Complier获取更高的编译速度,用Server Complier 来获取更好的编译质量。

为什么提供多个即时编译器与为什么提供多个垃圾收集器类似,都是为了适应不同的应用场景

jvm 
更新时间:2020-10-29 09:32:37

本文由 清水河恶霸 创作,如果您觉得本文不错,请随意赞赏
采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
原文链接:http://ql.magic-seven.top/2020/10/28/深入理解jvm原理4-为何jvm需要使用解释器和编译器并存的架构.html
最后更新:2020-10-29 09:32:37

评论

Your browser is out of date!

Update your browser to view this website correctly. Update my browser now

×